Refactoring naar common bases - also, werkende RTMP streaming! Jammer dat er nog maar 1 frame wordt verwerkt... maar het werkt!
This commit is contained in:
		
							parent
							
								
									f4c02f33d8
								
							
						
					
					
						commit
						2d0aafc179
					
				
					 27 changed files with 159 additions and 1594 deletions
				
			
		|  | @ -1,4 +1,4 @@ | |||
| SRC = main.cpp user.cpp sockets/sw_base.cpp sockets/sw_inet.cpp sockets/sw_unix.cpp | ||||
| SRC = main.cpp ../sockets/sw_base.cpp ../sockets/sw_inet.cpp ../sockets/sw_unix.cpp | ||||
| OBJ = $(SRC:.cpp=.o) | ||||
| OUT = Server_PLS | ||||
| INCLUDES =  | ||||
|  |  | |||
|  | @ -2,6 +2,5 @@ | |||
| 
 | ||||
| struct buffer{ | ||||
|   int number; | ||||
|   int size; | ||||
|   char * data; | ||||
|   FLV_Pack * FLV; | ||||
| };//buffer
 | ||||
|  |  | |||
|  | @ -1,14 +1,13 @@ | |||
| #include <iostream> | ||||
| #include "sockets/SocketW.h" | ||||
| #include "../sockets/SocketW.h" | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <cstdlib> | ||||
| #include <cstdio> | ||||
| #include "buffer.h" | ||||
| #include "user.h" | ||||
| #include "string.h" | ||||
| 
 | ||||
| #define BUFLEN 1000000 | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include "../util/flv.cpp" //FLV format parser
 | ||||
| #include "user.cpp" | ||||
| 
 | ||||
| int get_empty( user ** list, int amount ) { | ||||
|   for (int i = 0; i < amount; i++ ){ | ||||
|  | @ -18,27 +17,16 @@ int get_empty( user ** list, int amount ) { | |||
| } | ||||
| 
 | ||||
| int main( int argc, char * argv[] ) { | ||||
|   if (argc < 4) { | ||||
|     std::cout << "usage: " << argv[0] << " buffers_count total_buffersize max_clients" << std::endl; | ||||
|   if (argc < 3) { | ||||
|     std::cout << "usage: " << argv[0] << " buffers_count max_clients" << std::endl; | ||||
|     return 1; | ||||
|   } | ||||
|   int buffers = atoi(argv[1]); | ||||
|   int total_buffersize = atoi(argv[2]); | ||||
|   int connections = atoi(argv[3]); | ||||
|   int size_per_buffer = total_buffersize/buffers; | ||||
|   std::cout << "Size per buffer: " << size_per_buffer << std::endl; | ||||
|   int connections = atoi(argv[2]); | ||||
|   buffer ** ringbuf = (buffer**) calloc (buffers,sizeof(buffer*)); | ||||
|   for (int i = 0; i < buffers; i ++ ) { | ||||
|     ringbuf[i] = new buffer; | ||||
|     ringbuf[i]->data = (char*) malloc(size_per_buffer); | ||||
|   } | ||||
|   std::cout << "Successfully allocated " << total_buffersize << " bytes total buffer." << std::endl; | ||||
|   user ** connectionList = (user**) calloc (connections,sizeof(user*)); | ||||
|   for (int i = 0; i < connections; i++) { connectionList[i] = new user; } | ||||
|   char header[13];//FLV header is always 13 bytes
 | ||||
|   char metadata[BUFLEN]; | ||||
|   int ret = 0; | ||||
|   int frame_bodylength = 0; | ||||
|   for (int i = 0; i < buffers; ++i) ringbuf[i] = new buffer; | ||||
|   for (int i = 0; i < connections; ++i) connectionList[i] = new user; | ||||
|   int current_buffer = 0; | ||||
|   int open_connection = -1; | ||||
|   int lastproper = 0;//last properly finished buffer number
 | ||||
|  | @ -46,37 +34,23 @@ int main( int argc, char * argv[] ) { | |||
|   SWUnixSocket listener; | ||||
|   SWBaseSocket * incoming = 0; | ||||
|   SWBaseSocket::SWBaseError BError; | ||||
|   //read FLV header - 13 bytes
 | ||||
|   ret = fread(&header,1,13,stdin); | ||||
|   //TODO: check ret?
 | ||||
| 
 | ||||
|   listener.bind("/tmp/socketfile"); | ||||
|   unlink("../shared_socket"); | ||||
|   listener.bind("../shared_socket"); | ||||
|   listener.listen(); | ||||
|   listener.set_timeout(0,50000); | ||||
|    | ||||
|   //TODO: not while true, but while running - set running to false when kill signal is received!
 | ||||
|   while(true) { | ||||
| 
 | ||||
|   while(std::cin.good()) { | ||||
|     loopcount ++; | ||||
|     //invalidate the current buffer
 | ||||
|     ringbuf[current_buffer]->size = 0; | ||||
|     ringbuf[current_buffer]->number = -1; | ||||
|     if (std::cin.peek() == 'F') { | ||||
|       //new FLV file, read the file header again.
 | ||||
|       ret = fread(&header,1,13,stdin); | ||||
|     } else if( (int)std::cin.peek() == 12) { | ||||
|       //metadata encountered, let's filter it
 | ||||
|       ret = fread(&metadata,1,11,stdin); | ||||
|       frame_bodylength = 4; | ||||
|       frame_bodylength += metadata[3]; | ||||
|       frame_bodylength += (metadata[2] << 8); | ||||
|       frame_bodylength += (metadata[1] << 16); | ||||
|       ret = fread(&metadata,1,frame_bodylength,stdin); | ||||
|       FLV_Readheader(); | ||||
|     } else { | ||||
|       //read FLV frame header - 11 bytes
 | ||||
|       ret = fread(ringbuf[current_buffer]->data,1,11,stdin); | ||||
|       //TODO: Check ret?
 | ||||
|       FLV_GetPacket(ringbuf[current_buffer]->FLV); | ||||
|       //if video frame? (id 9) check for incoming connections
 | ||||
|       if (ringbuf[current_buffer]->data[0] == 9) { | ||||
|       if (ringbuf[current_buffer]->FLV->data[0] == 9) { | ||||
|         incoming = listener.accept(&BError); | ||||
|         if (incoming){ | ||||
|           open_connection = get_empty(connectionList,connections); | ||||
|  | @ -87,7 +61,7 @@ int main( int argc, char * argv[] ) { | |||
|             connectionList[open_connection]->MyBuffer = lastproper; | ||||
|             connectionList[open_connection]->MyBuffer_num = ringbuf[lastproper]->number; | ||||
|             //TODO: Do this more nicely?
 | ||||
|             if (connectionList[open_connection]->Conn->send(&header[0],13,NULL) != 13){ | ||||
|             if (connectionList[open_connection]->Conn->send(FLVHeader,13,0) != 13){ | ||||
|               connectionList[open_connection]->disconnect(); | ||||
|               std::cout << "Client " << open_connection << " failed to receive the header!" << std::endl; | ||||
|             } | ||||
|  | @ -97,15 +71,6 @@ int main( int argc, char * argv[] ) { | |||
|           } | ||||
|         } | ||||
|       } | ||||
|       //calculate body length of frame
 | ||||
|       frame_bodylength = 4; | ||||
|       frame_bodylength += ringbuf[current_buffer]->data[3]; | ||||
|       frame_bodylength += (ringbuf[current_buffer]->data[2] << 8); | ||||
|       frame_bodylength += (ringbuf[current_buffer]->data[1] << 16); | ||||
|       //read the rest of the frame
 | ||||
|       ret = fread(&ringbuf[current_buffer]->data[11],1,frame_bodylength,stdin); | ||||
|       //TODO: Check ret?
 | ||||
|       ringbuf[current_buffer]->size = frame_bodylength + 11; | ||||
|       ringbuf[current_buffer]->number = loopcount; | ||||
|       //send all connections what they need, if and when they need it
 | ||||
|       for (int i = 0; i < connections; i++) {connectionList[i]->Send(ringbuf, buffers);} | ||||
|  | @ -117,7 +82,7 @@ int main( int argc, char * argv[] ) { | |||
|   } | ||||
| 
 | ||||
|   // disconnect listener
 | ||||
|   std::cout << "Reached EOF of input" << std::endl; | ||||
|   listener.disconnect(); | ||||
|   //TODO: cleanup
 | ||||
|   return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1,22 +0,0 @@ | |||
| // C++ Socket Wrapper 
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindstr<74>m
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
| 
 | ||||
| #ifndef SocketW_H | ||||
| #define SocketW_H | ||||
| 
 | ||||
| #include "sw_base.h" | ||||
| #include "sw_unix.h" | ||||
| #include "sw_inet.h" | ||||
| 
 | ||||
| #endif //SocketW_H
 | ||||
|  | @ -1,764 +0,0 @@ | |||
| // C++ Socket Wrapper
 | ||||
| // SocketW base class
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindstr<74>m
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
|   | ||||
| #include "sw_base.h" | ||||
| #include <errno.h> | ||||
| #include <new> | ||||
| #include <time.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #ifndef __WIN32__ | ||||
|   #include <netdb.h> | ||||
|   #include <arpa/inet.h> | ||||
|   #include <fcntl.h> | ||||
|   #include <sys/select.h> | ||||
|   #include <sys/time.h> | ||||
|    | ||||
|   #define INVALID_SOCKET -1  //avoid M$ braindamage
 | ||||
| #else | ||||
|   //why use POSIX standards when we can make our own
 | ||||
|   //and frustrate people? (well known M$ policy)
 | ||||
|    | ||||
|   #ifndef EBADF | ||||
|     #define EBADF WSAEBADF | ||||
|   #endif | ||||
|    | ||||
|   #define ENOTSOCK WSAENOTSOCK | ||||
|   #define EOPNOTSUPP WSAEOPNOTSUPP | ||||
|   #define EADDRINUSE WSAEADDRINUSE | ||||
|   #define EWOULDBLOCK WSAEWOULDBLOCK | ||||
|   #define EMSGSIZE WSAEMSGSIZE | ||||
|   #define EINPROGRESS WSAEINPROGRESS | ||||
|   #define EALREADY WSAEALREADY | ||||
|   #define ECONNREFUSED WSAECONNREFUSED | ||||
|   #define ETIMEDOUT WSAETIMEDOUT | ||||
|   #define ENOTCONN WSAENOTCONN | ||||
|    | ||||
|   #ifndef EINTR | ||||
|     #define EINTR WSAEINTR | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MSG_NOSIGNAL | ||||
|   #define MSG_NOSIGNAL 0 | ||||
| #endif | ||||
| 
 | ||||
| // Socklen hack
 | ||||
| #if defined(__linux__) || defined(__FreeBSD__) // || defined(__bsdi__) || defined(__NetBSD__) too, perhaps? Bugreports, please!
 | ||||
|   #define sw_socklen_t socklen_t | ||||
| #elif defined(__WIN32__) || defined(__osf__) | ||||
|   #define sw_socklen_t int | ||||
| #else | ||||
|   #define sw_socklen_t unsigned int | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| #ifdef __WIN32__ | ||||
| //Win32 braindamage
 | ||||
| int close(int fd) | ||||
| { | ||||
| 	return closesocket(fd); | ||||
| } | ||||
| 
 | ||||
| int fcntl(int fd, int cmd, long arg) | ||||
| { | ||||
| 	unsigned long mode = arg; | ||||
| 
 | ||||
| 	return WSAIoctl(fd, cmd, &mode, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); | ||||
| } | ||||
| 
 | ||||
| void WSA_exit(void) | ||||
| { | ||||
| 	WSACleanup(); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| //====================================================================
 | ||||
| //== Error handling mode
 | ||||
| //====================================================================
 | ||||
| bool sw_DoThrow = false; | ||||
| bool sw_Verbose = true; | ||||
| 
 | ||||
| void sw_setThrowMode(bool throw_errors) | ||||
| { | ||||
| 	sw_DoThrow = throw_errors; | ||||
| } | ||||
| 
 | ||||
| void sw_setVerboseMode(bool verbose) | ||||
| { | ||||
| 	sw_Verbose = verbose; | ||||
| } | ||||
| 
 | ||||
| bool sw_getThrowMode(void) | ||||
| { | ||||
| 	return sw_DoThrow; | ||||
| } | ||||
| 
 | ||||
| bool sw_getVerboseMode(void) | ||||
| { | ||||
| 	return sw_Verbose; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //====================================================================
 | ||||
| //== Base error class
 | ||||
| //====================================================================
 | ||||
| SWBaseSocket::SWBaseError::SWBaseError() | ||||
| { | ||||
| 	be = ok; | ||||
| 	error_string = ""; | ||||
| 	failed_class = NULL; | ||||
| } | ||||
| 
 | ||||
| SWBaseSocket::SWBaseError::SWBaseError(base_error e) | ||||
| { | ||||
| 	be = e; | ||||
| 	error_string = ""; | ||||
| 	failed_class = NULL; | ||||
| } | ||||
| 
 | ||||
| string SWBaseSocket::SWBaseError::get_error() | ||||
| { | ||||
| 	return error_string; | ||||
| } | ||||
| 
 | ||||
| SWBaseSocket* SWBaseSocket::SWBaseError::get_failedClass(void) | ||||
| { | ||||
| 	return failed_class; | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::SWBaseError::set_errorString(string msg) | ||||
| {  | ||||
| 	error_string = msg; | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::SWBaseError::set_failedClass(SWBaseSocket *pnt) | ||||
| { | ||||
| 	failed_class = pnt; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::SWBaseError::operator==(SWBaseError e) | ||||
| { | ||||
| 	return be == e.be; | ||||
| } | ||||
| 		 | ||||
| bool SWBaseSocket::SWBaseError::operator!=(SWBaseError e) | ||||
| { | ||||
| 	return be != e.be; | ||||
| } | ||||
| 	 | ||||
| 
 | ||||
| //====================================================================
 | ||||
| //== SWBaseSocket
 | ||||
| //== Base class for sockets
 | ||||
| //====================================================================
 | ||||
| SWBaseSocket::SWBaseSocket() | ||||
| { | ||||
| 	//indicate nonopen
 | ||||
| 	myfd = -1; | ||||
| 	recv_close = false;	 | ||||
| 	 | ||||
| 	//init values
 | ||||
| 	error_string = ""; | ||||
| 	block_mode = blocking; | ||||
| 	fsend_ready = true; | ||||
| 	frecv_ready = true; | ||||
| 	tsec = 0; | ||||
| 	tusec = 0; | ||||
| 	 | ||||
| 	#ifdef __WIN32__ | ||||
| 	//kick winsock awake
 | ||||
| 	static bool firstuse = true; | ||||
| 	if( firstuse == true ){ | ||||
| 		WSAData wsaData; | ||||
| 		int nCode; | ||||
|     	if( (nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0 ){ | ||||
| 			handle_errno(NULL, "SWBaseSocket - WSAStartup() failed: "); | ||||
|         	exit(-1);  // Should never happend
 | ||||
|     	} | ||||
| 		 | ||||
| 		//cleanup at exit
 | ||||
| 		atexit(WSA_exit); | ||||
| 		firstuse = false; | ||||
| 	} | ||||
| 	#endif /* __WIN32__ */ | ||||
| } | ||||
| 
 | ||||
| SWBaseSocket::~SWBaseSocket() | ||||
| {	 | ||||
| 	if(myfd > 0) | ||||
| 		close(myfd); | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::listen(int qLimit, SWBaseError *error) | ||||
| { | ||||
| 	get_socket(); | ||||
| 
 | ||||
| 	//Avoid "Address already in use" thingie
 | ||||
| 	char yes=1; | ||||
| 	setsockopt(myfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); | ||||
| 	 | ||||
| 	if(::listen(myfd, qLimit) == -1){		 | ||||
| 		handle_errno(error, "SWBaseSocket::listen() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| SWBaseSocket* SWBaseSocket::accept(SWBaseError *error) | ||||
| { | ||||
| 	int remotefd = -1; | ||||
| 	sockaddr remoteAdr; | ||||
| 
 | ||||
| 	if( !waitRead(error) ) | ||||
| 		return NULL; | ||||
| 	 | ||||
| 	sw_socklen_t ssize = sizeof(sockaddr); | ||||
| 
 | ||||
| 	if((remotefd = ::accept(myfd, &remoteAdr, &ssize)) == int(INVALID_SOCKET)){ | ||||
| 		handle_errno(error, "SWBaseSocket::accept() error: "); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	 | ||||
| 	//nonblocking?
 | ||||
| 	if( block_mode == nonblocking ) | ||||
| 		fcntl(remotefd, F_SETFL, O_NONBLOCK); | ||||
| 	 | ||||
| 	/* Create new class*/ | ||||
| 	SWBaseSocket* remoteClass = create(remotefd, error); | ||||
| 	if( remoteClass == NULL ) | ||||
| 		return NULL; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return remoteClass; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::disconnect(SWBaseError *error) | ||||
| { | ||||
| 	int n = 0; | ||||
| 	char buf[256]; | ||||
| 
 | ||||
| 	if(myfd < 0){ | ||||
| 		set_error(error, notConnected, "SWBaseSocket::disconnect() - No connection"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	//close WR (this signals the peer) 
 | ||||
| 	if( shutdown(myfd, 1) != 0 ){ | ||||
| 		handle_errno(error, "SWBaseSocket::disconnect() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 
 | ||||
| 	SWBaseError err; | ||||
| 
 | ||||
| 	//wait for close signal from peer
 | ||||
| 	if( recv_close == false ){ | ||||
| 		while(true){ | ||||
| 			if( !waitRead(error) ) | ||||
| 				return false; | ||||
| 			 | ||||
| 			n = recv(buf, 256, &err); | ||||
| 			 | ||||
| 			if( n <= 0 ) | ||||
| 				break; | ||||
| 			if(block_mode == noWait){ | ||||
| 				//we don't want to block
 | ||||
| 				set_error(error, notReady, "SWBaseSocket::disconnect() - Need more time, call again"); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if( n != 0 ){ | ||||
| 		set_error(error, err, error_string); | ||||
| 		return false; //error
 | ||||
| 	} | ||||
| 	 | ||||
| 	//reset state
 | ||||
| 	reset(); | ||||
| 	 | ||||
| 	close(myfd); | ||||
| 	myfd = -1; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::close_fd() | ||||
| { | ||||
| 	if( myfd > 0 ){ | ||||
| 		close(myfd); | ||||
| 		myfd = -1; | ||||
| 		 | ||||
| 		//reset state
 | ||||
| 		reset(); | ||||
| 		 | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::send(const char *buf, int bytes, SWBaseError *error) | ||||
| {	 | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if(myfd < 0){ | ||||
| 		set_error(error, notConnected, "SWBaseSocket::send() - No connection"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
| 	if( !waitWrite(error) ) | ||||
| 		return -1; | ||||
| 		 | ||||
| 	ret = ::send(myfd, buf, bytes, MSG_NOSIGNAL); | ||||
| 	 | ||||
| 	if( ret < 0 ) | ||||
| 		handle_errno(error, "SWBaseSocket::send() error: "); | ||||
| 	else | ||||
| 		no_error(error); | ||||
| 	 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::fsend(const char *buf, int bytes, SWBaseError *error) | ||||
| { | ||||
| 	int n; | ||||
| 	int bytessent; | ||||
| 	 | ||||
| 	if(fsend_ready){ | ||||
| 		//First call
 | ||||
| 		fsend_bytesleft =  bytes; | ||||
| 		fsend_total = fsend_bytesleft;  //global var needed for resume
 | ||||
| 		bytessent = 0; | ||||
| 		fsend_ready = false;            //point of no return
 | ||||
| 	} | ||||
| 	else{ | ||||
| 		//resume
 | ||||
| 		bytessent = fsend_total - fsend_bytesleft; | ||||
| 	} | ||||
| 	 | ||||
| 	//send package
 | ||||
| 	while( fsend_bytesleft > 0 ){	 | ||||
| 		n = send( buf + bytessent , fsend_bytesleft, error ); | ||||
| 		 | ||||
| 		//return on error, wouldblock or nowait
 | ||||
| 		if( n < 0 ) | ||||
| 			return ( (bytessent > 0 )? -bytessent : -1 ); | ||||
| 			 | ||||
| 		bytessent += n; | ||||
| 		fsend_bytesleft -= n; | ||||
| 		 | ||||
| 		if ( block_mode == noWait  &&  fsend_bytesleft > 0 ){ | ||||
| 			set_error(error, notReady, "SWBaseSocket::fsend() - Need more time, call again"); | ||||
| 			return -bytessent; | ||||
| 		} | ||||
| 	}  | ||||
| 	 | ||||
| 	fsend_ready = true; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return fsend_total; | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::sendmsg(const string msg, SWBaseError *error) | ||||
| {	 | ||||
| 	return send(msg.c_str(), msg.size(), error); | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::fsendmsg(const string msg, SWBaseError *error) | ||||
| {	 | ||||
| 	return fsend(msg.c_str(), msg.size(), error); | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::recv(char *buf, int bytes, SWBaseError *error) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if(myfd < 0){ | ||||
| 		set_error(error, notConnected, "SWBaseSocket::recv() - No connection"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
| 	if( !waitRead(error) ) | ||||
| 		return -1; | ||||
| 	 | ||||
|  	ret = ::recv(myfd, buf, bytes, MSG_NOSIGNAL); | ||||
| 
 | ||||
| 	if( ret < 0 ) | ||||
| 		handle_errno(error, "SWBaseSocket::recv() error: "); | ||||
| 	else if( ret == 0 ){ | ||||
| 		recv_close = true;  //we  recived a close signal from peer
 | ||||
| 		set_error(error, terminated, "SWBaseSocket::recv() - Connection terminated by peer");	 | ||||
| 	}else | ||||
| 		no_error(error); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::frecv(char *buf, int bytes, SWBaseError *error) | ||||
| {	 | ||||
| 	int n; | ||||
| 	int bytesrecv; | ||||
| 	 | ||||
| 	if(frecv_ready){ | ||||
| 		//First call
 | ||||
| 		frecv_bytesleft =  bytes; | ||||
| 		frecv_total = frecv_bytesleft;  //global var needed for resume
 | ||||
| 		bytesrecv = 0; | ||||
| 		frecv_ready = false;            //point of no return
 | ||||
| 	} | ||||
| 	else{ | ||||
| 		//resume            
 | ||||
| 		bytesrecv = frecv_total - frecv_bytesleft; | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	//recv package
 | ||||
| 	while( frecv_bytesleft > 0 ){ | ||||
| 		n = recv( buf + bytesrecv , frecv_bytesleft, error ); | ||||
| 		 | ||||
| 		//return on error, wouldblock, nowait or timeout
 | ||||
| 		if( n < 0 ) | ||||
| 			return ( (bytesrecv > 0 )? -bytesrecv : -1 ); | ||||
| 		if( n == 0 ) | ||||
| 			return 0;  // terminated
 | ||||
| 			 | ||||
| 		bytesrecv += n; | ||||
| 		frecv_bytesleft -= n; | ||||
| 		 | ||||
| 		if ( block_mode == noWait  &&  frecv_bytesleft > 0 ){ | ||||
| 			set_error(error, notReady, "SWBaseSocket::frecv() - Need more time, call again"); | ||||
| 			return -bytesrecv; | ||||
| 		} | ||||
| 	}  | ||||
| 	 | ||||
| 	frecv_ready = true; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return frecv_total; | ||||
| } | ||||
| 
 | ||||
| string SWBaseSocket::recvmsg(int bytes, SWBaseError *error) | ||||
| { | ||||
| 	char *buf = new char[bytes+1]; | ||||
| 
 | ||||
| 	SWBaseError err; | ||||
| 	string msg = ""; | ||||
| 	int ret = recv(buf, bytes, &err); | ||||
| 	 | ||||
| 	if( ret > 0 ){ | ||||
| 		buf[ret]='\0';  // Make sure the string is null terminated
 | ||||
| 		msg = buf; | ||||
| 		no_error(error); | ||||
| 	} | ||||
| 	delete[] buf; | ||||
| 	 | ||||
| 	if( ret < 1 ) | ||||
| 		set_error(error, err, err.get_error()); | ||||
| 	 | ||||
| 	return msg; | ||||
| } | ||||
| 
 | ||||
| int SWBaseSocket::get_fd(SWBaseError *error) | ||||
| { | ||||
| 	if( myfd > 0 ){ | ||||
| 		no_error(error); | ||||
| 		return myfd; | ||||
| 	} | ||||
| 	 | ||||
| 	set_error(error, notConnected, "SWBaseSocket::get_fd() - No descriptor");		 | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::get_host(sockaddr *host, SWBaseError *error) | ||||
| { | ||||
| 	if( host == NULL){ | ||||
| 		set_error(error, fatal, "SWBaseSocket::get_host() - Got NULL pointer"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if(myfd < 0){ | ||||
| 		set_error(error, notConnected, "SWBaseSocket::get_host() - No socket"); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	sw_socklen_t tmp = sizeof(sockaddr); | ||||
| 	if( getsockname(myfd, host, &tmp) != 0 ){ | ||||
| 		handle_errno(error, "SWBaseSocket::get_host() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::get_peer(sockaddr *peer, SWBaseError *error) | ||||
| { | ||||
| 	if( peer == NULL){ | ||||
| 		set_error(error, fatal, "SWBaseSocket::get_peer() - Got NULL pointer"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if(myfd > 0){ | ||||
| 		sw_socklen_t tmp = sizeof(sockaddr); | ||||
| 		if( getpeername(myfd, peer, &tmp) != 0 ){ | ||||
| 			handle_errno(error, "SWBaseSocket::get_peer() error: "); | ||||
| 			return false; | ||||
| 		} | ||||
| 	}else{ | ||||
| 		set_error(error, notConnected, "SWBaseSocket::get_peer() - No connection"); | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::reset() | ||||
| { | ||||
| 	// Reset flags
 | ||||
| 	recv_close = false;	 | ||||
| 	 | ||||
| 	fsend_ready = true; | ||||
| 	frecv_ready = true; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::waitIO(io_type &type, SWBaseError *error) | ||||
| { | ||||
| 	if( block_mode != blocking ){ | ||||
| 		no_error(error); | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	// We prefere to wait with select() even if no timeout is set
 | ||||
| 	// as select() behaves more predictable
 | ||||
| 	 | ||||
| 	timeval t;  | ||||
| 	timeval *to = NULL;  // Indicate "wait for ever"
 | ||||
| 	t.tv_sec = tsec; | ||||
| 	t.tv_usec = tusec; | ||||
| 	  | ||||
| 	if( tsec > 0 || tusec > 0 ) | ||||
| 		to = &t; | ||||
| 		 | ||||
| 	fd_set readfds, writefds, exceptfds; | ||||
| 	 | ||||
| 	FD_ZERO(&readfds); | ||||
| 	FD_ZERO(&writefds); | ||||
| 	FD_ZERO(&exceptfds); | ||||
| 	FD_SET(myfd, &readfds); | ||||
| 	FD_SET(myfd, &writefds); | ||||
| 	FD_SET(myfd, &exceptfds); | ||||
| 	 | ||||
| 	int ret = 0; | ||||
| 	 | ||||
| 	switch (type){ | ||||
| 		case read: | ||||
| 			ret = select(myfd+1, &readfds, NULL, NULL, to); | ||||
| 			break; | ||||
| 		case write: | ||||
| 			ret = select(myfd+1, NULL, &writefds, NULL, to); | ||||
| 			break; | ||||
| 		case except: | ||||
| 			ret = select(myfd+1, NULL, NULL, &exceptfds, to); | ||||
| 			break; | ||||
| 		case rw: | ||||
| 			ret = select(myfd+1, &readfds, &writefds, NULL, to); | ||||
| 			break; | ||||
| 		case all: | ||||
| 			ret = select(myfd+1, &readfds, &writefds, &exceptfds, to); | ||||
| 			break; | ||||
| 	} | ||||
| 			 | ||||
| 	if( ret < 0 ){ | ||||
| 		handle_errno(error, "SWBaseSocket::waitIO() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 	if( ret == 0 ){ | ||||
| 		set_error(error, timeout, "SWBaseSocket::waitIO() timeout"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if( FD_ISSET(myfd, &readfds) ){ | ||||
| 		no_error(error); | ||||
| 		type = read; | ||||
| 		return true; | ||||
| 	} | ||||
| 	if( FD_ISSET(myfd, &writefds) ){ | ||||
| 		no_error(error); | ||||
| 		type = write; | ||||
| 		return true; | ||||
| 	} | ||||
| 	if( FD_ISSET(myfd, &exceptfds) ){ | ||||
| 		no_error(error); | ||||
| 		type = except; | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	set_error(error, fatal, "SWBaseSocket::waitIO() failed on select()"); | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::waitRead(SWBaseError *error) | ||||
| { | ||||
| 	io_type tmp = read; | ||||
| 	return waitIO(tmp, error); | ||||
| } | ||||
| 
 | ||||
| bool SWBaseSocket::waitWrite(SWBaseError *error) | ||||
| { | ||||
| 	io_type tmp = write; | ||||
| 	return waitIO(tmp, error); | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::print_error() | ||||
| { | ||||
| 	if( error_string.size() > 0 ) | ||||
| 		fprintf(stderr, "%s!\n", error_string.c_str()); | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::handle_errno(SWBaseError *error, string msg) | ||||
| { | ||||
| 	#ifndef __WIN32__ | ||||
| 	msg += strerror(errno); | ||||
| 	#else | ||||
| 	//stupid stupid stupid stupid M$
 | ||||
| 	switch (WSAGetLastError()){ | ||||
| 		case 0:                   msg += "No error"; break; | ||||
| 		case WSAEINTR:            msg += "Interrupted system call"; break; | ||||
| 		case WSAEBADF:            msg += "Bad file number"; break; | ||||
| 		case WSAEACCES:           msg += "Permission denied"; break; | ||||
| 		case WSAEFAULT:           msg += "Bad address"; break; | ||||
| 		case WSAEINVAL:           msg += "Invalid argument"; break; | ||||
| 		case WSAEMFILE:           msg += "Too many open sockets"; break; | ||||
| 		case WSAEWOULDBLOCK:      msg += "Operation would block"; break; | ||||
| 		case WSAEINPROGRESS:      msg += "Operation now in progress"; break; | ||||
| 		case WSAEALREADY:         msg += "Operation already in progress"; break; | ||||
| 		case WSAENOTSOCK:         msg += "Socket operation on non-socket"; break; | ||||
| 		case WSAEDESTADDRREQ:     msg += "Destination address required"; break; | ||||
| 		case WSAEMSGSIZE:         msg += "Message too long"; break; | ||||
| 		case WSAEPROTOTYPE:       msg += "Protocol wrong type for socket"; break; | ||||
| 		case WSAENOPROTOOPT:      msg += "Bad protocol option"; break; | ||||
| 		case WSAEPROTONOSUPPORT:  msg += "Protocol not supported"; break; | ||||
| 		case WSAESOCKTNOSUPPORT:  msg += "Socket type not supported"; break; | ||||
| 		case WSAEOPNOTSUPP:       msg += "Operation not supported on socket"; break; | ||||
| 		case WSAEPFNOSUPPORT:     msg += "Protocol family not supported"; break; | ||||
| 		case WSAEAFNOSUPPORT:     msg += "Address family not supported"; break; | ||||
| 		case WSAEADDRINUSE:       msg += "Address already in use"; break; | ||||
| 		case WSAEADDRNOTAVAIL:    msg += "Can't assign requested address"; break; | ||||
| 		case WSAENETDOWN:         msg += "Network is down"; break; | ||||
| 		case WSAENETUNREACH:      msg += "Network is unreachable"; break; | ||||
| 		case WSAENETRESET:        msg += "Net connection reset"; break; | ||||
| 		case WSAECONNABORTED:     msg += "Software caused connection abort"; break; | ||||
| 		case WSAECONNRESET:       msg += "Connection reset by peer"; break; | ||||
| 		case WSAENOBUFS:          msg += "No buffer space available"; break; | ||||
| 		case WSAEISCONN:          msg += "Socket is already connected"; break; | ||||
| 		case WSAENOTCONN:         msg += "Socket is not connected"; break; | ||||
| 		case WSAESHUTDOWN:        msg += "Can't send after socket shutdown"; break; | ||||
| 		case WSAETOOMANYREFS:     msg += "Too many references"; break; | ||||
| 		case WSAETIMEDOUT:        msg += "Connection timed out"; break; | ||||
| 		case WSAECONNREFUSED:     msg += "Connection refused"; break; | ||||
| 		case WSAELOOP:            msg += "Too many levels of symbolic links"; break; | ||||
| 		case WSAENAMETOOLONG:     msg += "File name too long"; break; | ||||
| 		case WSAEHOSTDOWN:        msg += "Host is down"; break; | ||||
| 		case WSAEHOSTUNREACH:     msg += "No route to host"; break; | ||||
| 		case WSAENOTEMPTY:        msg += "Directory not empty"; break; | ||||
| 		case WSAEPROCLIM:         msg += "Too many processes"; break; | ||||
| 		case WSAEUSERS:           msg += "Too many users"; break; | ||||
| 		case WSAEDQUOT:           msg += "Disc quota exceeded"; break; | ||||
| 		case WSAESTALE:           msg += "Stale NFS file handle"; break; | ||||
| 		case WSAEREMOTE:          msg += "Too many levels of remote in path"; break; | ||||
| 		case WSASYSNOTREADY:      msg += "Network system is unavailable"; break; | ||||
| 		case WSAVERNOTSUPPORTED:  msg += "Winsock version out of range"; break; | ||||
| 		case WSANOTINITIALISED:   msg += "WSAStartup not yet called"; break; | ||||
| 		case WSAEDISCON:          msg += "Graceful shutdown in progress"; break; | ||||
| 		case WSAHOST_NOT_FOUND:   msg += "Host not found"; break; | ||||
| 		case WSANO_DATA:          msg += "No host data of that type was found"; break; | ||||
| 		default:                  msg += "Unknown Winsock error: " + WSAGetLastError(); break; | ||||
| 	} | ||||
| 	#endif | ||||
| 	 | ||||
| 	int errorno; | ||||
| 	 | ||||
| 	//Win32 braindamage
 | ||||
| 	#ifdef __WIN32__ | ||||
| 	  errorno = WSAGetLastError(); | ||||
| 	#else | ||||
| 	  errorno = errno; | ||||
| 	#endif | ||||
| 	 | ||||
| 	SWBaseError e; | ||||
| 	 | ||||
| 	if( errorno == EADDRINUSE ) | ||||
| 		e = portInUse; | ||||
| 	else if( errorno == EAGAIN || errorno == EWOULDBLOCK ) | ||||
| 		e = notReady; | ||||
| 	else if( errorno == EMSGSIZE ) | ||||
| 		e = msgTooLong; | ||||
| 	else if( errorno == EINPROGRESS || errorno == EALREADY ) | ||||
| 		e = notReady; | ||||
| 	else if( errorno == ECONNREFUSED || errorno == ETIMEDOUT ) | ||||
| 		e = noResponse; | ||||
| 	else if( errorno == ENOTCONN || errorno == EBADF || errorno == ENOTSOCK ) | ||||
| 		e = notConnected; | ||||
| 	else if( errorno == EPIPE ){ | ||||
| 		e = terminated; | ||||
| 		recv_close = true; | ||||
| 	}else if( errorno == EINTR ) | ||||
| 		e = interrupted; | ||||
| 	else | ||||
| 		e = fatal; //default
 | ||||
| 		 | ||||
| 	set_error(error, e, msg); | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::no_error(SWBaseError *error) | ||||
| { | ||||
| 	if(error != NULL){ | ||||
| 		*error = ok; | ||||
| 		error->error_string = ""; | ||||
| 		error->failed_class = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void SWBaseSocket::set_error(SWBaseError *error, SWBaseError name, string msg) | ||||
| { | ||||
| 	error_string = msg; | ||||
| 
 | ||||
| 	if(error != NULL){ | ||||
| 		*error = name; | ||||
| 		error->error_string = msg; | ||||
| 		error->failed_class = this; | ||||
| 	}else{ | ||||
| 		if( sw_Verbose ) | ||||
| 			print_error(); | ||||
| 		 | ||||
| 		if( sw_DoThrow ){ | ||||
| 			SWBaseError e; | ||||
| 			e = name; | ||||
| 			e.error_string = msg; | ||||
| 			e.failed_class = this; | ||||
| 			throw e; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1,205 +0,0 @@ | |||
| // C++ Socket Wrapper
 | ||||
| // SocketW base socket header 
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindström
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
|   | ||||
| #ifndef sw_base_H | ||||
| #define sw_base_H | ||||
| 
 | ||||
| #include "sw_internal.h" | ||||
| 
 | ||||
| #include <unistd.h> | ||||
| #include <string> | ||||
| 
 | ||||
| // Set error handling mode
 | ||||
| // throw_errors == true  : Throws the error class on unhandled errors
 | ||||
| // throw_errors == false : Exit on unhandled errors
 | ||||
| // verbose == true       : Prints the error message to stderr on unhandled errors
 | ||||
| //
 | ||||
| // Default is throw_errors == false and verbose == true
 | ||||
| void sw_setThrowMode(bool throw_errors); | ||||
| void sw_setVerboseMode(bool verbose); | ||||
| bool sw_getThrowMode(void); | ||||
| bool sw_getVerboseMode(void); | ||||
| 
 | ||||
| 
 | ||||
| // Abstract base class for streaming sockets
 | ||||
| class DECLSPEC SWBaseSocket | ||||
| { | ||||
| public:	 | ||||
| 	SWBaseSocket(); | ||||
| 	virtual ~SWBaseSocket(); | ||||
| 	 | ||||
| 	// Error types
 | ||||
| 	// ok           - operation succesful
 | ||||
| 	// fatal        - unspecified error
 | ||||
| 	// notReady     - you should call the function again
 | ||||
| 	//                indicates that the function would block (if nowait/nonblocking)
 | ||||
| 	// portInUse    - this port is used by another socket ( on listen() )
 | ||||
| 	// notConnected - socket not connected (or valid)
 | ||||
| 	// msgTooLong   - the message size it too big for send()
 | ||||
| 	// terminated   - connection terminated (by peer)
 | ||||
| 	// noResponse   - can't connect() to peer
 | ||||
| 	// timeout      - a read/write operation timed out (only if a timeout value is set and if in blocking mode)
 | ||||
| 	// interrupted  - operation was interrupted by a nonblocked signal
 | ||||
| 	enum base_error{ok, fatal, notReady, portInUse, notConnected, msgTooLong, terminated, noResponse, timeout, interrupted}; | ||||
| 	 | ||||
| 	class DECLSPEC SWBaseError | ||||
| 	{ | ||||
| 	public: | ||||
| 		SWBaseError(); | ||||
| 		SWBaseError(base_error e); | ||||
| 		 | ||||
| 		virtual ~SWBaseError(){;} | ||||
| 		 | ||||
| 		virtual std::string get_error(); | ||||
| 		virtual SWBaseSocket* get_failedClass(void); | ||||
| 		 | ||||
| 		virtual bool operator==(SWBaseError e); | ||||
| 		virtual bool operator!=(SWBaseError e); | ||||
| 		 | ||||
| 		virtual void set_errorString(std::string msg); | ||||
| 		virtual void set_failedClass(SWBaseSocket *pnt); | ||||
| 	protected: | ||||
| 		friend class SWBaseSocket; | ||||
| 		 | ||||
| 		// The base error type
 | ||||
| 		base_error be; | ||||
| 		 | ||||
| 		// Human readable error string
 | ||||
| 		std::string error_string; | ||||
| 		 | ||||
| 		// A pointer to the class causing the error
 | ||||
| 		SWBaseSocket *failed_class; | ||||
| 	}; | ||||
| 	 | ||||
| 	 | ||||
| 	// Note: If no SWBaseError class is provided with a method call (==NULL),
 | ||||
| 	// SocketW will print the error to stderr and exit or throw on errors.
 | ||||
| 	 | ||||
| 	// Note: All bool functions returns true on success.
 | ||||
| 	 | ||||
| 	// Block mode
 | ||||
| 	// blocking    - everythings blocks until completly done
 | ||||
| 	// noWait      - operations block but only once
 | ||||
| 	//               useful with blocking w. select()
 | ||||
| 	// nonblocking - don't block (you should use select())
 | ||||
| 	enum block_type{blocking, noWait, nonblocking}; | ||||
| 	 | ||||
| 	 | ||||
| 	// Connection methods
 | ||||
| 	// qLimit - the maximum length the queue of pending connections.
 | ||||
| 	// Accept returns a new socket class connected with peer (should be
 | ||||
| 	// freed with delete) or NULL on failure. You can cast the class to
 | ||||
| 	// the correct type if you need to ( eg. (SWInetSocket *)mysocket ).
 | ||||
| 	virtual bool listen(int qLimit = 5, SWBaseError *error = NULL); | ||||
| 	virtual SWBaseSocket* accept(SWBaseError *error = NULL); | ||||
| 	// bind() and connect() are implemented in child classes
 | ||||
| 	 | ||||
| 	// do the disconnect ritual (signal peer, wait for close singal and close socket)
 | ||||
| 	virtual bool disconnect(SWBaseError *error = NULL); | ||||
| 	 | ||||
| 	// force close socket
 | ||||
| 	virtual bool close_fd();  //use with care, disconnect() is cleaner
 | ||||
| 
 | ||||
| 	// Direct I/O (raw)
 | ||||
| 	// Can send/recv less bytes than specified!
 | ||||
| 	// Returns the actual amount of bytes sent/recv on sucess
 | ||||
| 	// and an negative integer on failure.
 | ||||
| 	virtual int send(const char *buf, int bytes, SWBaseError *error = NULL); | ||||
| 	virtual int sendmsg(const std::string msg, SWBaseError *error = NULL); | ||||
| 	virtual int recv(char *buf, int bytes, SWBaseError *error = NULL); | ||||
| 	virtual std::string recvmsg(int bytes = 256, SWBaseError *error = NULL); | ||||
| 	 | ||||
| 	// Forced I/O
 | ||||
| 	// Force system to send/recv the specified amount of bytes.
 | ||||
| 	// On nowait/nonblocking: might return with notReady and then you
 | ||||
| 	// MUST call the same method again (eg. wait with select() to know when) 
 | ||||
| 	// with the same parameters until the operation is finished.
 | ||||
| 	// Returns 'bytes' when finished, negative integer on failure and
 | ||||
| 	// 'notReady'. In the 'notReady' case, -(return value) is the amount of
 | ||||
| 	// bytes sent/recv so far.
 | ||||
| 	virtual int fsend(const char *buf, int bytes, SWBaseError *error = NULL); | ||||
| 	virtual int fsendmsg(const std::string msg, SWBaseError *error = NULL); | ||||
| 	virtual int frecv(char *buf, int bytes, SWBaseError *error = NULL); | ||||
| 	 | ||||
| 	// Tools
 | ||||
| 	// get_fd() - get socket descriptor, can be used with select()
 | ||||
| 	// returns -1 on failure.
 | ||||
| 	// get_host/peer fills the provided structures with info about the
 | ||||
| 	// host/peer (see man unix & ip).
 | ||||
| 	// SWInetSocket has some more tools for TCP/IP sockets.
 | ||||
| 	virtual int get_fd(SWBaseError *error); | ||||
| 	virtual bool get_host(sockaddr *host, SWBaseError *error = NULL); | ||||
| 	virtual bool get_peer(sockaddr *peer, SWBaseError *error = NULL); | ||||
| 	 | ||||
| 	// Set recv timeout (only in blocking mode).
 | ||||
| 	// set_timeout(0,0) means wait forever (default).
 | ||||
| 	// This affects the functions recv(), send(), accept() and disconnect()
 | ||||
| 	// and others that use those, i.e. all frecvmsg().
 | ||||
| 	void set_timeout(Uint32 sec, Uint32 usec){ tsec = sec, tusec = usec; } | ||||
| 	 | ||||
| 	// Error handling
 | ||||
| 	virtual void print_error(); //prints the last error if any to stderr
 | ||||
| 	virtual std::string get_error(){return error_string;}  //returns a human readable error string
 | ||||
| 
 | ||||
| protected: | ||||
| 	// get a new socket if myfd < 0
 | ||||
| 	virtual void get_socket()=0; | ||||
| 	 | ||||
| 	// create a new class for accept() using socketdescriptor
 | ||||
| 	virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error)=0; | ||||
| 
 | ||||
| 	// reset state
 | ||||
| 	virtual void reset(); | ||||
| 
 | ||||
| 	// wait for I/O (with timeout)
 | ||||
| 	enum io_type{read, write, except, rw, all}; | ||||
| 	virtual bool waitIO(io_type &type, SWBaseError *error); | ||||
| 	bool waitRead(SWBaseError *error); | ||||
| 	bool waitWrite(SWBaseError *error); | ||||
| 
 | ||||
| 	// internal error handling
 | ||||
| 	virtual void handle_errno(SWBaseError *error, std::string msg); | ||||
| 	virtual void no_error(SWBaseError *error); | ||||
| 	virtual void set_error(SWBaseError *error, SWBaseError name, std::string msg); | ||||
| 
 | ||||
| 	// our socket descriptor
 | ||||
| 	int myfd; | ||||
| 	 | ||||
| 	// last error
 | ||||
| 	std::string error_string; | ||||
| 
 | ||||
| 	// data for fsend
 | ||||
| 	bool fsend_ready; | ||||
| 	int fsend_total; | ||||
| 	int fsend_bytesleft; | ||||
| 	 | ||||
| 	// data for frecv
 | ||||
| 	bool frecv_ready; | ||||
| 	int frecv_total; | ||||
| 	int frecv_bytesleft; | ||||
| 		 | ||||
| 	// have we recived a shutdown signal?
 | ||||
| 	bool recv_close; | ||||
| 
 | ||||
| 	//blocking mode (set by child classes)
 | ||||
| 	block_type block_mode; | ||||
| 	 | ||||
| 	//timeout for waitIO()
 | ||||
| 	int tsec; | ||||
| 	int tusec; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif /* sw_base_H */ | ||||
|  | @ -1,249 +0,0 @@ | |||
| // C++ Socket Wrapper
 | ||||
| // SocketW Inet socket
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindström
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
| 
 | ||||
| #include "sw_inet.h" | ||||
| 
 | ||||
| #ifndef __WIN32__ | ||||
|   #include <netdb.h> | ||||
|   #include <arpa/inet.h> | ||||
|   #include <fcntl.h> | ||||
|   #include <sys/select.h> | ||||
|   #include <sys/time.h> | ||||
| #else | ||||
|   #define F_SETFL FIONBIO | ||||
|   #define O_NONBLOCK 1 | ||||
|    | ||||
|   //Defined in sw_base.cxx
 | ||||
|   extern int close(int fd); | ||||
|   extern int fcntl(int fd, int cmd, long arg); | ||||
| #endif | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| //====================================================================
 | ||||
| //== SWInetSocket
 | ||||
| //== Inet (TCP/IP) streaming sockets
 | ||||
| //====================================================================
 | ||||
| SWInetSocket::SWInetSocket(block_type block) | ||||
| { | ||||
| 	block_mode = block; | ||||
| } | ||||
| 
 | ||||
| SWInetSocket::~SWInetSocket() | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void SWInetSocket::get_socket() | ||||
| { | ||||
| 	if( myfd < 0 ){ | ||||
| 		myfd = socket(PF_INET, SOCK_STREAM, 0); | ||||
| 	 | ||||
| 		if( block_mode == nonblocking ) | ||||
| 			fcntl(myfd, F_SETFL, O_NONBLOCK); | ||||
| 			 | ||||
| 		//reset state	
 | ||||
| 		reset(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| SWBaseSocket* SWInetSocket::create(int socketdescriptor, SWBaseError *error) | ||||
| { | ||||
| 	SWInetSocket* remoteClass; | ||||
| 		 | ||||
| 	/* Create new class*/ | ||||
| 	remoteClass = new SWInetSocket(block_mode); | ||||
| 	remoteClass->myfd = socketdescriptor; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return remoteClass; | ||||
| } | ||||
| 
 | ||||
| bool SWInetSocket::bind(int port, SWBaseError *error) | ||||
| { | ||||
| 	return bind(port, "", error); | ||||
| } | ||||
| 
 | ||||
| bool SWInetSocket::bind(int port, string host, SWBaseError *error) | ||||
| { | ||||
| 	hostent *h; | ||||
| 	in_addr inp; 	 | ||||
| 
 | ||||
|  	if( host.size() > 0 ){ | ||||
| 		// Bind to a specific address
 | ||||
| 	 | ||||
| 		if( (h = gethostbyname(host.c_str())) == NULL ){ | ||||
|  			set_error(error, fatal, "SWInetSocket::bind() - Can't get host by name"); | ||||
|  			return false; | ||||
|  		} | ||||
| 		 | ||||
| 		inp = *((in_addr *)h->h_addr); | ||||
| 	}else{ | ||||
| 		// Bind to any
 | ||||
| 		inp.s_addr = INADDR_ANY; | ||||
| 	} | ||||
| 	 | ||||
| 
 | ||||
| 	get_socket(); | ||||
| 
 | ||||
| 	sockaddr_in myAdr; | ||||
| 
 | ||||
| 	memset(&myAdr, 0, sizeof(myAdr)); | ||||
| 	myAdr.sin_family = AF_INET; | ||||
| 	myAdr.sin_port = htons(port); | ||||
| 	myAdr.sin_addr.s_addr = inp.s_addr; | ||||
| 
 | ||||
| 	if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ | ||||
| 		handle_errno(error, "SWInetSocket::bind() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 		 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool SWInetSocket::connect(int port, string hostname, SWBaseError *error) | ||||
| { | ||||
| 	get_socket(); | ||||
| 
 | ||||
| 	hostent *host; | ||||
| 
 | ||||
| 	if( (host = gethostbyname(hostname.c_str())) == NULL ){ | ||||
| 		set_error(error, fatal, "SWInetSocket::connect() - Can't get host by name"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	sockaddr_in remoteAdr; | ||||
| 
 | ||||
| 	memset(&remoteAdr, 0, sizeof(remoteAdr)); | ||||
| 	remoteAdr.sin_family = AF_INET; | ||||
| 	remoteAdr.sin_port = htons(port); | ||||
| 	remoteAdr.sin_addr = *((in_addr *)host->h_addr); | ||||
| 
 | ||||
| 	if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ | ||||
| 		handle_errno(error, "SWInetSocket::connect() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| string SWInetSocket::get_peerAddr(SWBaseError *error) | ||||
| { | ||||
| 	sockaddr_in adr; | ||||
| 	 | ||||
| 	if( !get_peer((sockaddr *)&adr, error) ) | ||||
| 		return ""; | ||||
| 	 | ||||
| 	char *pnt; | ||||
| 	 | ||||
| 	if( (pnt = inet_ntoa(adr.sin_addr)) == NULL ){ | ||||
| 		set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer address"); | ||||
| 		return ""; | ||||
| 	} | ||||
| 	string name(pnt); | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return name; | ||||
| } | ||||
| 
 | ||||
| int SWInetSocket::get_peerPort(SWBaseError *error) | ||||
| { | ||||
| 	sockaddr_in adr; | ||||
| 	 | ||||
| 	if( !get_peer((sockaddr *)&adr, error) ) | ||||
| 		return -1; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	 | ||||
| 	return ntohs(adr.sin_port); | ||||
| } | ||||
| 
 | ||||
| string SWInetSocket::get_peerName(SWBaseError *error) | ||||
| { | ||||
| 	string name = get_peerAddr(error); | ||||
| 	if(name.size() < 1) | ||||
|  		return ""; | ||||
| 
 | ||||
| 	 | ||||
| 	hostent *h; 	 | ||||
| 
 | ||||
|  	if( (h = gethostbyname(name.c_str())) == NULL ){ | ||||
|  		set_error(error, fatal, "SWInetSocket::get_peerName() - Can't get peer by address"); | ||||
|  		return ""; | ||||
|  	} | ||||
| 	string host_name(h->h_name); | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return host_name; | ||||
| } | ||||
| 
 | ||||
| string SWInetSocket::get_hostAddr(SWBaseError *error) | ||||
| { | ||||
| 	//We need to get the real address, so we must
 | ||||
| 	//first get this computers host name and then
 | ||||
| 	//translate that into an address!
 | ||||
| 
 | ||||
| 	string name = get_hostName(error); | ||||
| 	if( name.size() < 1 ) | ||||
| 		return ""; | ||||
| 		 | ||||
| 	hostent *host; | ||||
| 
 | ||||
| 	if( (host = gethostbyname(name.c_str())) == NULL ){ | ||||
| 		set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host by name"); | ||||
| 		return ""; | ||||
| 	} | ||||
| 	 | ||||
| 	char *pnt; | ||||
| 	 | ||||
| 	if( (pnt = inet_ntoa(*((in_addr *)host->h_addr))) == NULL){ | ||||
| 		set_error(error, fatal, "SWInetSocket::get_hostAddr() - Can't get host address"); | ||||
| 		return ""; | ||||
| 	} | ||||
| 	 | ||||
| 	string adr(pnt); | ||||
| 	 | ||||
| 	return adr; | ||||
| } | ||||
| 
 | ||||
| int SWInetSocket::get_hostPort(SWBaseError *error) | ||||
| { | ||||
| 	sockaddr_in adr; | ||||
| 	 | ||||
| 	if( !get_host((sockaddr *)&adr, error) ) | ||||
| 		return -1; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	 | ||||
| 	return ntohs(adr.sin_port); | ||||
| } | ||||
| 
 | ||||
| string SWInetSocket::get_hostName(SWBaseError *error) | ||||
| { | ||||
| 	char buf[256]; | ||||
| 	 | ||||
| 	if( gethostname(buf, 256) != 0 ){ | ||||
| 		handle_errno(error, "SWInetSocket::gethostname() error: "); | ||||
| 		return ""; | ||||
| 	} | ||||
| 	 | ||||
| 	string msg(buf); | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return msg; | ||||
| } | ||||
|  | @ -1,48 +0,0 @@ | |||
| // C++ Socket Wrapper 
 | ||||
| // SocketW Inet socket header
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindström
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
| 
 | ||||
| #ifndef sw_inet_H | ||||
| #define sw_inet_H | ||||
| 
 | ||||
| #include "sw_internal.h" | ||||
| #include "sw_base.h" | ||||
| #include <string> | ||||
| 
 | ||||
| // Simple streaming TCP/IP class
 | ||||
| class DECLSPEC SWInetSocket : public SWBaseSocket | ||||
| { | ||||
| public: | ||||
| 	SWInetSocket(block_type block=blocking); | ||||
| 	virtual ~SWInetSocket(); | ||||
| 	 | ||||
| 	virtual bool bind(int port, SWBaseError *error = NULL);  //use port=0 to get any free port
 | ||||
| 	virtual bool bind(int port, std::string host, SWBaseError *error = NULL); //you can also specify the host interface to use
 | ||||
| 	virtual bool connect(int port, std::string hostname, SWBaseError *error = NULL); | ||||
| 	 | ||||
| 	// Tools
 | ||||
| 	// Gets IP addr, name or port.
 | ||||
| 	virtual std::string get_peerAddr(SWBaseError *error = NULL); | ||||
| 	virtual int get_peerPort(SWBaseError *error = NULL); | ||||
| 	virtual std::string get_peerName(SWBaseError *error = NULL); | ||||
| 	virtual std::string get_hostAddr(SWBaseError *error = NULL); | ||||
| 	virtual int get_hostPort(SWBaseError *error = NULL); | ||||
| 	virtual std::string get_hostName(SWBaseError *error = NULL); | ||||
| 	 | ||||
| protected:	 | ||||
| 	virtual void get_socket(); | ||||
| 	virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); | ||||
| }; | ||||
| 
 | ||||
| #endif /* sw_inet_H */ | ||||
|  | @ -1,75 +0,0 @@ | |||
| // C++ Socket Wrapper
 | ||||
| // SocketW internal header 
 | ||||
| //
 | ||||
| // Started 030823
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindstr<74>m
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
|   | ||||
| #ifndef sw_internal_H | ||||
| #define sw_internal_H | ||||
| 
 | ||||
| // This header is included in all *.h files
 | ||||
| 
 | ||||
| #ifndef __WIN32__ | ||||
|   #include <sys/types.h>  | ||||
|   #include <sys/socket.h>  | ||||
|   #include <netinet/in.h> | ||||
|   #include <sys/un.h> | ||||
| #else | ||||
|   #include <winsock2.h> | ||||
|    | ||||
|   #define F_SETFL FIONBIO | ||||
|   #define O_NONBLOCK 1 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef _SDL_H | ||||
| 
 | ||||
| // Define general types
 | ||||
| typedef unsigned char  Uint8; | ||||
| typedef signed char    Sint8; | ||||
| typedef unsigned short Uint16; | ||||
| typedef signed short   Sint16; | ||||
| typedef unsigned int   Uint32; | ||||
| typedef signed int     Sint32; | ||||
| 
 | ||||
| // It's VERY important that these types really have the right sizes!
 | ||||
| // This black magic is from SDL
 | ||||
| #define COMPILE_TIME_ASSERT(name, x)               \ | ||||
|        typedef int _dummy_ ## name[(x) * 2 - 1] | ||||
| COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); | ||||
| COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); | ||||
| COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); | ||||
| COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); | ||||
| COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); | ||||
| COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); | ||||
| #undef COMPILE_TIME_ASSERT | ||||
| 
 | ||||
| #endif /* _SDL_H */ | ||||
| 
 | ||||
| // Some compilers use a special export keyword
 | ||||
| #ifndef DECLSPEC | ||||
|   #ifdef __BEOS__ | ||||
|     #if defined(__GNUC__) | ||||
|       #define DECLSPEC __declspec(dllexport) | ||||
|     #else | ||||
|       #define DECLSPEC __declspec(export) | ||||
|     #endif | ||||
|   #else | ||||
|     #ifdef WIN32 | ||||
|       #define DECLSPEC __declspec(dllexport) | ||||
|     #else | ||||
|       #define DECLSPEC | ||||
|     #endif | ||||
|   #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #endif /* sw_internal_H */ | ||||
|  | @ -1,99 +0,0 @@ | |||
| // C++ Socket Wrapper
 | ||||
| // SocketW Unix socket
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindström
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
|   | ||||
| #include "sw_unix.h" | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| 
 | ||||
| //====================================================================
 | ||||
| //== SWUnixSocket
 | ||||
| //== Unix streaming sockets
 | ||||
| //====================================================================
 | ||||
| #ifndef __WIN32__ | ||||
| 
 | ||||
| SWUnixSocket::SWUnixSocket(block_type block) | ||||
| {	 | ||||
| 	block_mode = block; | ||||
| } | ||||
| 
 | ||||
| SWUnixSocket::~SWUnixSocket() | ||||
| { | ||||
| 	//nothing here
 | ||||
| } | ||||
| 
 | ||||
| void SWUnixSocket::get_socket() | ||||
| { | ||||
| 	if( myfd < 0 ){ | ||||
| 		myfd = socket(PF_UNIX, SOCK_STREAM, 0); | ||||
| 	 | ||||
| 		if( block_mode == nonblocking ) | ||||
| 			fcntl(myfd, F_SETFL, O_NONBLOCK); | ||||
| 		 | ||||
| 		//reset state	
 | ||||
| 		reset(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| SWBaseSocket* SWUnixSocket::create(int socketdescriptor, SWBaseError *error) | ||||
| { | ||||
| 	SWUnixSocket* remoteClass; | ||||
| 		 | ||||
| 	/* Create new class*/ | ||||
| 	remoteClass = new SWUnixSocket(block_mode); | ||||
| 	remoteClass->myfd = socketdescriptor; | ||||
| 	 | ||||
| 	no_error(error); | ||||
| 	return remoteClass; | ||||
| } | ||||
| 
 | ||||
| bool SWUnixSocket::bind(string path, SWBaseError *error) | ||||
| { | ||||
| 	get_socket(); | ||||
| 	 | ||||
| 	sockaddr_un myAdr; | ||||
| 
 | ||||
| 	myAdr.sun_family = AF_UNIX; | ||||
| 	strncpy(myAdr.sun_path, path.c_str(), path.size()+1); | ||||
| 
 | ||||
| 	if(::bind(myfd, (sockaddr *)&myAdr, sizeof(myAdr)) == -1){ | ||||
| 		handle_errno(error, "SWUnixSocket::bind() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 		 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool SWUnixSocket::connect(string path, SWBaseError *error) | ||||
| { | ||||
| 	get_socket(); | ||||
| 
 | ||||
| 	sockaddr_un remoteAdr; | ||||
| 	 | ||||
| 	remoteAdr.sun_family = AF_UNIX; | ||||
| 	strncpy(remoteAdr.sun_path, path.c_str(), path.size()+1); | ||||
| 
 | ||||
| 	if(::connect(myfd, (sockaddr *)&remoteAdr, sizeof(remoteAdr)) == -1){ | ||||
| 		handle_errno(error, "SWUnixSocket::connect() error: "); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	no_error(error); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| #endif /* __WIN32__ */ | ||||
|  | @ -1,41 +0,0 @@ | |||
| // C++ Socket Wrapper 
 | ||||
| // SocketW Unix socket header
 | ||||
| //
 | ||||
| // Started 020316
 | ||||
| //
 | ||||
| // License: LGPL v2.1+ (see the file LICENSE)
 | ||||
| // (c)2002-2003 Anders Lindström
 | ||||
| 
 | ||||
| /***********************************************************************
 | ||||
|  *  This library is free software; you can redistribute it and/or      * | ||||
|  *  modify it under the terms of the GNU Lesser General Public         * | ||||
|  *  License as published by the Free Software Foundation; either       * | ||||
|  *  version 2.1 of the License, or (at your option) any later version. * | ||||
|  ***********************************************************************/ | ||||
| 
 | ||||
| #ifndef sw_unix_H | ||||
| #define sw_unix_H | ||||
| #ifndef __WIN32__ | ||||
| 
 | ||||
| #include "sw_internal.h" | ||||
| #include "sw_base.h" | ||||
| #include <string> | ||||
| 
 | ||||
| // Simple streaming Unix class
 | ||||
| class DECLSPEC SWUnixSocket : public SWBaseSocket | ||||
| { | ||||
| public: | ||||
| 	SWUnixSocket(block_type block=blocking); | ||||
| 	~SWUnixSocket(); | ||||
| 
 | ||||
| 	// bind and connect to the socket file "path"
 | ||||
| 	virtual bool bind(std::string path, SWBaseError *error = NULL); | ||||
| 	virtual bool connect(std::string path, SWBaseError *error = NULL); | ||||
| 
 | ||||
| protected: | ||||
| 	virtual void get_socket(); | ||||
| 	virtual SWBaseSocket* create(int socketdescriptor, SWBaseError *error); | ||||
| }; | ||||
| 
 | ||||
| #endif /* __WIN32__ */ | ||||
| #endif /* sw_unix_H */ | ||||
|  | @ -1,4 +1,20 @@ | |||
| #include "user.h" | ||||
| #include "buffer.h" | ||||
| #include "../sockets/SocketW.h" | ||||
| #include <iostream> | ||||
| 
 | ||||
| class user{ | ||||
|   public: | ||||
|     user(); | ||||
|     ~user(); | ||||
|     void disconnect(); | ||||
|     void connect(SWBaseSocket * newConnection); | ||||
|     void Send(buffer ** ringbuf, int buffers); | ||||
|     bool is_connected; | ||||
|     SWUnixSocket * Conn; | ||||
|     int MyBuffer; | ||||
|     int MyBuffer_num; | ||||
| };//user
 | ||||
| 
 | ||||
| 
 | ||||
| user::user() { | ||||
|   Conn = NULL; | ||||
|  | @ -37,12 +53,12 @@ void user::Send(buffer ** ringbuf, int buffers){ | |||
|     return; | ||||
|   } | ||||
|   SWBaseSocket::SWBaseError err; | ||||
|   int ret = Conn->fsend(ringbuf[MyBuffer]->data, ringbuf[MyBuffer]->size, &err); | ||||
|   int ret = Conn->fsend(ringbuf[MyBuffer]->FLV->data, ringbuf[MyBuffer]->FLV->len, &err); | ||||
|   if ((err != SWBaseSocket::ok) && (err != SWBaseSocket::notReady)){ | ||||
|     disconnect(); | ||||
|     return; | ||||
|   } | ||||
|   if (ret == ringbuf[MyBuffer]->size){ | ||||
|   if (ret == ringbuf[MyBuffer]->FLV->len){ | ||||
|     //completed a send - switch to next buffer
 | ||||
|     MyBuffer++; | ||||
|     MyBuffer %= buffers; | ||||
|  |  | |||
|  | @ -1,18 +0,0 @@ | |||
| #pragma once | ||||
| #include "buffer.h" | ||||
| #include "sockets/SocketW.h" | ||||
| #include <iostream> | ||||
| 
 | ||||
| class user{ | ||||
|   public: | ||||
|     user(); | ||||
|     ~user(); | ||||
|     void disconnect(); | ||||
|     void connect(SWBaseSocket * newConnection); | ||||
|     void Send(buffer ** ringbuf, int buffers); | ||||
|     bool is_connected; | ||||
|     SWUnixSocket * Conn; | ||||
|     int MyBuffer; | ||||
|     int MyBuffer_num; | ||||
| };//user
 | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Thulinma
						Thulinma