network.cc
上传用户:aoeyumen
上传日期:2007-01-06
资源大小:3329k
文件大小:14k
- /*
- File: network.cc
- By: Alex Theo de Jong
- Created: April 1996
- Description:
- This file contains all network functions to be used with the mpeg2player. This
- is a temporary solution. The complete AtmSocket API should be used for this
- in order to use configuration/testing facilities. Hopefully we can do that im
- June/July 1996
- */
- #ifdef __GNUG__
- #pragma implementation
- #endif
- #include "athread.hh"
- #include <stdio.h>
- #include <stdlib.h>
- #include <String.h>
- #include <fstream.h>
- #include <sys/time.h>
- #include <sys/errno.h>
- #include <fcntl.h>
- #ifdef LINUX
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/poll.h>
- //#include <asm/poll.h>
- #define POLLRDNORM 0x0040
- #endif
- #ifdef IRIX
- #include <bstring.h>
- #include <stropts.h>
- #include <poll.h>
- #endif
- #include "error.hh"
- #include "debug.hh"
- #include "util.hh"
- #include "network.hh"
- // Socket File
- SocketFile::SocketFile(const char* filen){
- TRACER("SocketFile::SocketFile(const char* filen)");
- filename=filen;
- /*
- file.open(filename.chars());
- if (!file){
- error("could not open file `" << filename << "' for reading");
- }
- */
- if (filen[0] == '-' && filen[1] == ' ')
- socketfd = 0;
- else if ((socketfd=open(filename.chars(), O_RDONLY | O_NDELAY))<=0){
- error("could not open file `" << filename << "' for reading");
- }
- }
- SocketFile::~SocketFile(){
- TRACER("SocketFile::~SocketFile()");
- /*
- if (filename.length()){
- file.close();
- }
- */
- ::close(socketfd);
- }
- int SocketFile::recv(unsigned char* data, int size){
- DEBUGGER("int SocketFile::recv(unsigned char* data, int size)");
- bfr=data;
- read_bytes=0;
- do {
- /*
- if ((bytes=(file.read(data, size).gcount()))<=0)
- */
- if ((bytes=read(socketfd, bfr, size - read_bytes))<=0)
- return bytes;
- bfr+=bytes;
- read_bytes+=bytes;
- }
- while (read_bytes<size);
- return read_bytes;
- };
- int SocketFile::close(){
- TRACER("int SocketFile::close()");
- if (filename.length() && socketfd>=0){
- return ::close(socketfd);
- }
- return -1;
- }
- // Socket TCP
- SocketTcp::SocketTcp(unsigned int asap, unsigned int pdu_size){
- TRACER("SocketTcp::SocketTcp(unsigned int asap, unsigned int pdu_size)");
- sockaddr_in server_addr;
-
- if ((socketfd=::socket(AF_INET, SOCK_STREAM, IPPROTO_IP))<0){
- error("can't open stream socket");
- exit(1);
- }
-
- #if (defined(IRIX) || defined(IRIX_PTHREAD))
- bzero(&server_addr, sizeof(server_addr));
- #else
- memset((char*) &server_addr, 0, sizeof(server_addr));
- #endif
-
- #ifdef SOLARIS
- struct hostent* host=0;
- // Try ATM
- String name(getenv("HOSTNAME"));
- name+="-atm"; // default extension for ATM
- if (name.length()!=0 && (host=gethostbyname(name.chars()))==0){
- // if no ATM, try regular HOSTNAME address
- if ((host=gethostbyname(getenv("HOSTNAME")))==0){
- error("could not get host by name");
- athr_exit(0);
- }
- }
- server_addr.sin_addr.s_addr =((struct in_addr *) host->h_addr_list[0])->s_addr;
- #endif
-
- server_addr.sin_family=AF_INET;
- server_addr.sin_port=htons(asap);
- while (1){
- if (::bind(socketfd, (struct sockaddr*) &server_addr, sizeof(server_addr))<0){
- ::close(socketfd);
- error("could not bind local address");
- exit(1);
- }
- else break;
- asap++;
- }
-
- int reuseaddr=1;
- if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuseaddr, sizeof(reuseaddr))<0){
- error("can't set sender socket option (SO_REUSEADDR)"); exit(1);
- }
-
- if (pdu_size){
- unsigned int read_size=pdu_size;
- if (setsockopt(socketfd,SOL_SOCKET,SO_SNDBUF,(char*)&read_size,sizeof(read_size))<0){
- error("can't set socket option (SO_SNDBUF)"); exit(1);
- }
- if (setsockopt(socketfd,SOL_SOCKET,SO_RCVBUF,(char*)&read_size,sizeof(read_size))<0){
- error("can't set socket option (SO_RCVBUF)"); exit(1);
- }
- }
-
- int alive=1;
- if (setsockopt(socketfd,SOL_SOCKET,SO_KEEPALIVE,(char*)&alive,sizeof(alive))<0){
- error("can't set socket option (SO_KEEPALIVE)"); exit(1);
- }
- int error=0;
- #ifdef LINUX
- socklen_t error_len=sizeof(error);
- #else
- int error_len=sizeof(error);
- #endif
- if (getsockopt(socketfd, SOL_SOCKET, SO_ERROR, (char*) &error, &error_len)<0){
- error("can't get sender socket option (SO_ERROR)"); exit(1);
- }
-
- if (::listen(socketfd, 1)<0){
- error("could not listen to connection");
- exit(0);
- }
- }
- SocketTcp::~SocketTcp(){
- TRACER("SocketTcp::~SocketTcp");
- ::close(fd);
- }
- int SocketTcp::accept(){
- DEBUGGER("int SocketTcp::accept()");
- sockaddr_in client_addr;
- #ifdef LINUX
- socklen_t client_len=sizeof(client_addr);
- #else
- int client_len=sizeof(client_addr);
- #endif
- #if (defined(IRIX) || defined(IRIX_PTHREAD))
- bzero(&client_addr, sizeof(client_addr));
- #else
- memset((char*) &client_addr, 0, sizeof(client_addr));
- #endif
-
- if ((fd=::accept(socketfd, (struct sockaddr*) &client_addr, &client_len))<=0){
- error("could not accept connection (" << itoa(errno) << ")");
- athr_exit(0);
- }
- ::close(socketfd);
- message("received connection on TCP!");
-
- return fd;
- }
- int SocketTcp::recv(unsigned char* data, int size){
- DEBUGGER("int SocketTcp::recv(unsigned char* data, int size)");
- bfr=data;
- read_bytes=0;
- do {
- if ((bytes=::read(fd, bfr, size-read_bytes))<=0)
- return bytes;
- bfr+=bytes;
- read_bytes+=bytes;
- }
- while (read_bytes<size);
- #ifdef DEEPDEBUG
- static int count=0;
- unsigned int test=((data[0]<<24) | (data[1] << 16) | (data[2]<<8) | data[3]); printf("First 4 bytes=%xn", test);
- test=((data[188]<<24) | (data[189] << 16) | (data[190]<<8) | data[191]);
- printf("First 4 bytes=%xn", test);
- if (count++==10) exit(0);
- #endif
- return read_bytes;
- };
- int SocketTcp::close(){
- int err=::close(fd);
- TRACER("int SocketTcp::close()");
- return err;
- }
- // Socket UDP
- SocketUdp::SocketUdp(unsigned int asap, unsigned int pdu_size){
- TRACER("SocketUdp::SocketUdp()");
- sockaddr_in server_addr;
-
- if ((socketfd=::socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))<0){
- error("can't open dgram socket");
- exit(1);
- }
-
- #if (defined(IRIX) || defined(IRIX_PTHREAD))
- bzero(&server_addr, sizeof(server_addr));
- #else
- memset((char*) &server_addr, 0, sizeof(server_addr));
- #endif
-
- #ifdef SOLARIS
- struct hostent* host=0;
- // if (option==1){
- if ((host=gethostbyname(getenv("HOSTNAME")))==0){
- error("could not get host by name");
- athr_exit(0);
- }
- /*
- else {
- String name(getenv("HOSTNAME"));
- name+="-atm"; // default extension for ATM
- if (name.length()!=0 && (host=gethostbyname(name.chars()))==0){
- error("could not get host by name");
- athr_exit(0);
- }
- }
- */
- server_addr.sin_addr.s_addr =((struct in_addr *) host->h_addr_list[0])->s_addr;
- #endif
-
- server_addr.sin_family=AF_INET;
- server_addr.sin_port=htons(asap);
- while (1){
- if (::bind(socketfd, (struct sockaddr*) &server_addr, sizeof(server_addr))<0){
- ::close(socketfd);
- error("could not bind local address");
- exit(1);
- }
- else break;
- asap++;
- }
-
- int reuseaddr=1;
- if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuseaddr, sizeof(reuseaddr))<0){
- error("can't set sender socket option (SO_REUSEADDR)"); exit(1);
- }
-
- if (pdu_size){
- unsigned int read_size=pdu_size;
- if (setsockopt(socketfd,SOL_SOCKET,SO_SNDBUF,(char*)&read_size,sizeof(read_size))<0){
- error("can't set socket option (SO_SNDBUF)"); exit(1);
- }
- if (setsockopt(socketfd,SOL_SOCKET,SO_RCVBUF,(char*)&read_size,sizeof(read_size))<0){
- error("can't set socket option (SO_RCVBUF)"); exit(1);
- }
- }
-
- int alive=1;
- if (setsockopt(socketfd,SOL_SOCKET,SO_KEEPALIVE,(char*)&alive,sizeof(alive))<0){
- error("can't set socket option (SO_KEEPALIVE)"); exit(1);
- }
- int error=0;
- #ifdef LINUX
- socklen_t error_len=sizeof(error);
- #else
- int error_len=sizeof(error);
- #endif
- if (getsockopt(socketfd, SOL_SOCKET, SO_ERROR, (char*) &error, &error_len)<0){
- error("can't get sender socket option (SO_ERROR)"); exit(1);
- }
-
- pcli_addr=(sockaddr*) &cli_addr;
- cli_len=sizeof(cli_addr);
- }
- SocketUdp::~SocketUdp(){
- TRACER("SocketUdp::~SocketUdp");
- ::close(fd);
- }
- int SocketUdp::accept(){
- TRACER("int SocketUdp::accept()");
- fd=socketfd;
- message("received connection on UDP!");
- return fd;
- }
- int SocketUdp::recv(unsigned char* data, int size){
- DEBUGGER("int SocketUdp::recv(unsigned char* data, int size)");
- bfr=data;
- read_bytes=0;
- do {
- #ifdef LINUX
- if ((bytes=::recvfrom(fd, (char*) bfr, size-read_bytes, 0, pcli_addr, (socklen_t*)&cli_len))==size)
- #else
- if ((bytes=::recvfrom(fd, (char*) bfr, size-read_bytes, 0, pcli_addr, &cli_len))==size)
- #endif
- return bytes;
- bfr+=bytes;
- read_bytes+=bytes;
- }
- while (read_bytes<size);
- return read_bytes;
- }
- int SocketUdp::close(){
- int err=::close(fd);
- TRACER("int SocketUdp::close()");
- return err;
- }
- #ifdef FORE_ATM
- // Socket ATM SPANS
- SocketAtmSpans::SocketAtmSpans(unsigned int sap) : asap(sap) {
- TRACER("SocketAtmSpans::SocketAtmSpans(unsigned int sap)");
- Atm_info info;
- aal_type=aal_type_5;
- dataflow=duplex;
-
- if ((socketfd=atm_open(ATMDEVICE, O_RDWR, &info))<0){
- atm_error("atm_open : ");
- exit(1);
- }
-
- int queue_size=1;
- if (atm_bind(socketfd, asap, &asap, queue_size)<0){
- atm_error("atm_bind");
- exit(1);
- }
- }
- SocketAtmSpans::~SocketAtmSpans(){
- TRACER("SocketAtmSpans::~SocketAtmSpans()");
- ::atm_close(fd);
- }
- int SocketAtmSpans::accept(){
- TRACER("int SocketAtmSpans::accept()");
- Atm_qos qos_server;
- int conn_id(0);
-
- if (atm_listen(socketfd, &conn_id, &atm_endpoint, &qos_server, &aal_type) < 0){
- atm_error("atm_listen");
- exit(1);
- }
- qos.peak_bandwidth.target = qos_server.peak_bandwidth.target;
- qos.peak_bandwidth.minimum = qos_server.peak_bandwidth.minimum;
- qos.mean_bandwidth.target = qos_server.mean_bandwidth.target;
- qos.mean_bandwidth.minimum = qos_server.mean_bandwidth.minimum;
- qos.mean_burst.target = qos_server.mean_burst.target;
- qos.mean_burst.minimum = qos_server.mean_burst.minimum;
-
- if (atm_accept(socketfd, socketfd, conn_id, &qos, dataflow) < 0) {
- atm_error("atm_accept");
- exit(1);
- }
- fd=socketfd;
- message("received connection on ATM SPANS!");
- return fd;
- }
- int SocketAtmSpans::recv(unsigned char* data, int size){
- DEBUGGER("int SocketAtmSpans::recv(unsigned char* data, int size)");
- bfr=data;
- read_bytes=0;
- do {
- if ((bytes=::atm_recv(fd, (caddr_t) bfr, size-read_bytes))<=0)
- // ATM returns -1 when connection is terminated
- return (bytes==-1 || bytes==0) ? 0 : bytes;
- bfr+=bytes;
- read_bytes+=bytes;
- }
- while (read_bytes<size);
- return read_bytes;
- }
- int SocketAtmSpans::close(){
- int err=::atm_close(fd);
- TRACER("int SocketAtmSpans::close()");
- return err;
- }
- // class ATM PVC
- SocketAtmPvc::SocketAtmPvc(unsigned int vci, unsigned int vpi){
- TRACER("SocketAtmPvc::SocketAtmPvc(unsigned int vci, unsigned int vpi)");
- Atm_info info;
- Atm_conn_resource qos;
- aal_type=aal_type_5;
- if ((socketfd=atm_open(ATMDEVICE, O_RDWR, &info))<0){
- atm_error("atm_open: ");
- exit(1);
- }
- /*
- if (info.mtu < pdu_size){
- error("sdu size to big for maximum ATM mtu");
- exit(1);
- }
- */
- qos.peak_bandwidth = 50000; // set some dummy values
- qos.mean_bandwidth = 500000;
- vpvc= (vpi & 0x00000FFF) << 16;
- vpvc+=(vci & 0x0000FFFF);
- if (atm_bind_pvc(socketfd, vpvc, aal_type, &qos)!=0){
- atm_error("atm_bind_pvc");
- exit(1);
- }
- }
- SocketAtmPvc::~SocketAtmPvc(){
- TRACER("SocketAtmPvc::~SocketAtmPvc()");
- ::atm_close(fd);
- }
- int SocketAtmPvc::accept(){
- TRACER("int SocketAtmPvc::accept()");
- fd=socketfd; // ready to receive data
- message("received connection on ATM PVC!");
- return fd;
- }
- int SocketAtmPvc::recv(unsigned char* data, int size){
- DEBUGGER("int SocketAtmPvc::recv(unsigned char* data, int size)");
- bfr=data;
- read_bytes=0;
- do {
- if ((bytes=::atm_recvfrom(fd, (caddr_t) bfr, size-read_bytes, &vpvc))<=1){
- if (bytes==1) return 0; // eof EOF protocol if using a PVC
- return bytes;
- }
- bfr+=bytes;
- read_bytes+=bytes;
- }
- while (read_bytes<size);
- return read_bytes;
- }
-
- int SocketAtmPvc::close(){
- int err=::atm_close(fd);
- TRACER("int SocketAtmPvc::close()");
- return err;
- }
- #endif // FORE_ATM
- // SocketMulti waits at several ports and accepts the one first activated
- SocketMulti::SocketMulti(unsigned int asap, int pdu_size, unsigned int vci, unsigned int vpi){
- TRACER("SocketMulti::SocketMulti(unsigned int asap, int pdu_size, vci, int vpi)");
- sockets=new Socket*[SOCKETMULTI_MAX];
- count=0;
- sockets[count++]=new SocketTcp(asap, pdu_size);
- sockets[count++]=new SocketUdp(asap, pdu_size);
- #ifdef FORE_ATM
- // test to find ATM board
- Atm_info info;
- int dummy;
- if ((dummy=atm_open(ATMDEVICE, O_RDWR, &info))>0){
- atm_close(dummy);
- // found an ATM board; thus include these while wating for connection
- sockets[count++]=new SocketAtmSpans(asap);
- sockets[count++]=new SocketAtmPvc(vci, vpi);
- }
- sockets[count]=0;
- #endif
- }
- SocketMulti::SocketMulti(const char* name){
- TRACER("SocketMulti::SocketMulti(const char* name)");
-
- sockets=0;
- socket=new SocketFile(name);
- count=1;
- }
- SocketMulti::~SocketMulti(){
- if (sockets){
- for (int i=0; sockets[i]!=0; i++)
- delete sockets[i];
- delete[] sockets;
- }
- else delete socket;
- }
- int SocketMulti::accept(){
- TRACER("int SocketMulti::accept()");
- if (sockets==0) return 0;
- pollfd fds[SOCKETMULTI_MAX];
- for (int i=0; i<count; i++){
- fds[i].fd=sockets[i]->socketfd;
- fds[i].events= POLLRDNORM | POLLPRI; // POLLIN | POLLRDBAND | );
- }
- message("waiting for connection ... ");
- if (poll(fds, count, -1)<0){
- error("could not call poll");
- exit(1);
- }
- for (int j=0; j<count; j++){
- if (fds[j].revents>0){
- return (socket=sockets[j])->accept();
- }
- }
- error("failed to find event after poll");
- return -1;
- }