project_files/frontlib/net/netbase.c
changeset 7234 613998625a3c
child 7275 15f722e0b96f
equal deleted inserted replaced
7230:240620f46dd7 7234:613998625a3c
       
     1 #include "netbase.h"
       
     2 #include "../util/buffer.h"
       
     3 #include "../util/logging.h"
       
     4 #include "../util/util.h"
       
     5 #include "../socket.h"
       
     6 
       
     7 #include <string.h>
       
     8 #include <stdbool.h>
       
     9 #include <stdlib.h>
       
    10 #include <stdio.h>
       
    11 
       
    12 #define NET_READBUFFER_LIMIT (1024*1024)
       
    13 
       
    14 struct _flib_netbase {
       
    15 	flib_vector *readBuffer;
       
    16 	flib_tcpsocket *sock;
       
    17 };
       
    18 
       
    19 flib_netbase *flib_netbase_create(const char *server, uint16_t port) {
       
    20 	flib_netbase *result = NULL;
       
    21 	flib_netbase *newNet =  flib_calloc(1, sizeof(flib_netbase));
       
    22 
       
    23 	if(newNet) {
       
    24 		newNet->readBuffer = flib_vector_create();
       
    25 		newNet->sock = flib_socket_connect(server, port);
       
    26 		if(newNet->readBuffer && newNet->sock) {
       
    27 			flib_log_i("Connected to server %s:%u", server, (unsigned)port);
       
    28 			result = newNet;
       
    29 			newNet = NULL;
       
    30 		}
       
    31 	}
       
    32 	flib_netbase_destroy(newNet);
       
    33 
       
    34 	return result;
       
    35 }
       
    36 
       
    37 void flib_netbase_destroy(flib_netbase *net) {
       
    38 	if(net) {
       
    39 		flib_socket_close(net->sock);
       
    40 		flib_vector_destroy(net->readBuffer);
       
    41 		free(net);
       
    42 	}
       
    43 }
       
    44 
       
    45 bool flib_netbase_connected(flib_netbase *net) {
       
    46 	if(!net) {
       
    47 		flib_log_e("null parameter in flib_netbase_connected");
       
    48 		return false;
       
    49 	} else if(net->sock) {
       
    50 		return true;
       
    51 	} else {
       
    52 		return false;
       
    53 	}
       
    54 }
       
    55 
       
    56 /**
       
    57  * Parses and returns a message, and removes it from the vector.
       
    58  */
       
    59 static flib_netmsg *parseMessage(flib_vector *vec) {
       
    60 	const uint8_t *partStart = flib_vector_data(vec);
       
    61 	const uint8_t *end = partStart+flib_vector_size(vec);
       
    62 	flib_netmsg *result = flib_netmsg_create();
       
    63 	if(!result) {
       
    64 		return NULL;
       
    65 	}
       
    66 
       
    67 	while(1) {
       
    68 		const uint8_t *partEnd = memchr(partStart, '\n', end-partStart);
       
    69 		if(!partEnd) {
       
    70 			// message incomplete
       
    71 			flib_netmsg_destroy(result);
       
    72 			return NULL;
       
    73 		} else if(partEnd-partStart == 0) {
       
    74 			// Zero-length part, message end marker. Remove the message from the vector.
       
    75 			uint8_t *vectorStart = flib_vector_data(vec);
       
    76 			size_t msgLen = partEnd+1-vectorStart;
       
    77 			memmove(vectorStart, partEnd+1, flib_vector_size(vec)-msgLen);
       
    78 			flib_vector_resize(vec, flib_vector_size(vec)-msgLen);
       
    79 			return result;
       
    80 		} else {
       
    81 			if(flib_netmsg_append_part(result, partStart, partEnd-partStart)) {
       
    82 				flib_netmsg_destroy(result);
       
    83 				return NULL;
       
    84 			}
       
    85 			partStart = partEnd+1; // Skip the '\n'
       
    86 		}
       
    87 	}
       
    88 	return NULL; // Never reached
       
    89 }
       
    90 
       
    91 /**
       
    92  * Receive some bytes and add them to the buffer.
       
    93  * Returns the number of bytes received.
       
    94  * Automatically closes the socket if an error occurs
       
    95  * and sets sock=NULL.
       
    96  */
       
    97 static int receiveToBuffer(flib_netbase *net) {
       
    98 	uint8_t buffer[256];
       
    99 	if(!net->sock) {
       
   100 		return 0;
       
   101 	} else if(flib_vector_size(net->readBuffer) > NET_READBUFFER_LIMIT) {
       
   102 		flib_log_e("Net connection closed: Net message too big");
       
   103 		flib_socket_close(net->sock);
       
   104 		net->sock = NULL;
       
   105 		return 0;
       
   106 	} else {
       
   107 		int size = flib_socket_nbrecv(net->sock, buffer, sizeof(buffer));
       
   108 		if(size>=0) {
       
   109 			flib_vector_append(net->readBuffer, buffer, size);
       
   110 			return size;
       
   111 		} else {
       
   112 			flib_socket_close(net->sock);
       
   113 			net->sock = NULL;
       
   114 			return 0;
       
   115 		}
       
   116 	}
       
   117 }
       
   118 
       
   119 flib_netmsg *flib_netbase_recv_message(flib_netbase *net) {
       
   120 	if(!net) {
       
   121 		flib_log_e("null parameter in flib_netbase_recv_message");
       
   122 		return NULL;
       
   123 	}
       
   124 
       
   125 	flib_netmsg *msg;
       
   126 	while(!(msg=parseMessage(net->readBuffer))
       
   127 			&& receiveToBuffer(net)) {}
       
   128 
       
   129 	if(msg) {
       
   130 		return msg;
       
   131 	} else if(!net->sock && flib_vector_size(net->readBuffer)>0) {
       
   132 		// Connection is down and we didn't get a complete message, just flush the rest.
       
   133 		flib_vector_resize(net->readBuffer, 0);
       
   134 	}
       
   135 	return NULL;
       
   136 }
       
   137 
       
   138 static void logSentMsg(const uint8_t *data, size_t len) {
       
   139 	if(flib_log_isActive(FLIB_LOGLEVEL_DEBUG)) {
       
   140 		flib_log_d("[NET OUT][%03u]%*.*s",(unsigned)len, (unsigned)len, (unsigned)len, data);
       
   141 	}
       
   142 }
       
   143 
       
   144 int flib_netbase_send_raw(flib_netbase *net, const void *data, size_t len) {
       
   145 	if(!net || (!data && len>0)) {
       
   146 		flib_log_e("null parameter in flib_netbase_send_raw");
       
   147 		return -1;
       
   148 	}
       
   149 	if(!net->sock) {
       
   150 		flib_log_w("flib_netbase_send_raw: Not connected.");
       
   151 		return -1;
       
   152 	}
       
   153 
       
   154 	if(flib_socket_send(net->sock, data, len) == len) {
       
   155 		logSentMsg(data, len);
       
   156 		return 0;
       
   157 	} else {
       
   158 		flib_log_w("Failed or incomplete write: net connection lost.");
       
   159 		flib_socket_close(net->sock);
       
   160 		net->sock = NULL;
       
   161 		return -1;
       
   162 	}
       
   163 }
       
   164 
       
   165 int flib_netbase_send_message(flib_netbase *net, flib_netmsg *msg) {
       
   166 	if(!net || !msg) {
       
   167 		flib_log_e("null parameter in flib_netbase_send_message");
       
   168 		return -1;
       
   169 	}
       
   170 
       
   171 	size_t totalSize = 0;
       
   172 	for(int i=0; i<msg->partCount; i++) {
       
   173 		totalSize += strlen(msg->parts[i]) + 1;
       
   174 	}
       
   175 	totalSize++; // Last part ends in two '\n' instead of one
       
   176 
       
   177 	uint8_t *buffer = flib_malloc(totalSize);
       
   178 	if(!buffer) {
       
   179 		return -1;
       
   180 	}
       
   181 	size_t pos = 0;
       
   182 	for(int i=0; i<msg->partCount; i++) {
       
   183 		size_t partsize = strlen(msg->parts[i]);
       
   184 		memcpy(buffer+pos, msg->parts[i], partsize);
       
   185 		pos += partsize;
       
   186 		buffer[pos++] = '\n';
       
   187 	}
       
   188 	buffer[pos++] = '\n';
       
   189 	return flib_netbase_send_raw(net, buffer, pos);
       
   190 }
       
   191 
       
   192 int flib_netbase_sendf(flib_netbase *net, const char *format, ...) {
       
   193 	int result = -1;
       
   194 	if(!net || !format) {
       
   195 		flib_log_e("null parameter in flib_netbase_sendf");
       
   196 	} else {
       
   197 		va_list argp;
       
   198 		va_start(argp, format);
       
   199 		char *buffer = flib_vasprintf(format, argp);
       
   200 		if(buffer) {
       
   201 			result = flib_netbase_send_raw(net, buffer, strlen(buffer));
       
   202 		}
       
   203 		free(buffer);
       
   204 		va_end(argp);
       
   205 	}
       
   206 	return result;
       
   207 }
       
   208 
       
   209 flib_netmsg *flib_netmsg_create() {
       
   210 	flib_netmsg *result = flib_calloc(1, sizeof(flib_netmsg));
       
   211 	if(result) {
       
   212 		result->partCount = 0;
       
   213 		result->parts = NULL;
       
   214 		return result;
       
   215 	} else {
       
   216 		return NULL;
       
   217 	}
       
   218 }
       
   219 
       
   220 void flib_netmsg_destroy(flib_netmsg *msg) {
       
   221 	if(msg) {
       
   222 		for(int i=0; i<msg->partCount; i++) {
       
   223 			free(msg->parts[i]);
       
   224 		}
       
   225 		free(msg->parts);
       
   226 		free(msg);
       
   227 	}
       
   228 }
       
   229 
       
   230 int flib_netmsg_append_part(flib_netmsg *msg, const void *part, size_t partlen) {
       
   231 	int result = -1;
       
   232 	if(!msg) {
       
   233 		flib_log_e("null parameter in flib_netmsg_append_part");
       
   234 	} else {
       
   235 		char **newParts = realloc(msg->parts, (msg->partCount+1)*sizeof(*msg->parts));
       
   236 		if(newParts) {
       
   237 			msg->parts = newParts;
       
   238 			msg->parts[msg->partCount] = flib_malloc(partlen+1);
       
   239 			if(msg->parts[msg->partCount]) {
       
   240 				memcpy(msg->parts[msg->partCount], part, partlen);
       
   241 				msg->parts[msg->partCount][partlen] = 0;
       
   242 				msg->partCount++;
       
   243 				result = 0;
       
   244 			}
       
   245 		}
       
   246 	}
       
   247 	return result;
       
   248 }