📄 network.cc
字号:
/* 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 FileSocketFile::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] == '\0') 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 TCPSocketTcp::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=%x\n", test); test=((data[188]<<24) | (data[189] << 16) | (data[190]<<8) | data[191]); printf("First 4 bytes=%x\n", test); if (count++==10) exit(0);#endif return read_bytes;};int SocketTcp::close(){ int err=::close(fd); TRACER("int SocketTcp::close()"); return err;}// Socket UDPSocketUdp::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 SPANSSocketAtmSpans::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 PVCSocketAtmPvc::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 activatedSocketMulti::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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -