tcp_socket.c
Go to the documentation of this file.
00001 00041 #include "tcp_socket.h" 00042 00043 #include "cfg/cfg_tcpsocket.h" 00044 00045 #define LOG_LEVEL TCPSOCKET_LOG_LEVEL 00046 #define LOG_FORMAT TCPSOCKET_LOG_FORMAT 00047 #include <cfg/log.h> 00048 #include <cpu/byteorder.h> 00049 00050 #include <lwip/ip_addr.h> 00051 #include <lwip/api.h> 00052 #include <lwip/netif.h> 00053 #include <lwip/netbuf.h> 00054 #include <lwip/tcpip.h> 00055 00056 00057 INLINE void close_socket(TcpSocket *socket) 00058 { 00059 /* Clean all previuos states */ 00060 netbuf_delete(socket->rx_buf_conn); 00061 socket->rx_buf_conn = NULL; 00062 socket->remaning_data_len = 0; 00063 00064 if (!socket->sock) 00065 return; 00066 00067 /* Close socket if was open */ 00068 netconn_delete(socket->sock); 00069 socket->sock = NULL; 00070 return; 00071 } 00072 00073 static bool tcpsocket_reconnect(TcpSocket *socket) 00074 { 00075 LOG_ERR("Reconnecting..\n"); 00076 00077 /* Close socket if was open */ 00078 close_socket(socket); 00079 00080 /* If we are in server mode we do nothing */ 00081 if (socket->handler) 00082 return false; 00083 00084 /* Start with new connection */ 00085 socket->sock = netconn_new(NETCONN_TCP); 00086 if(!socket->sock) 00087 { 00088 LOG_ERR("Unabe to alloc new connection\n"); 00089 socket->error = -1; 00090 goto error; 00091 } 00092 00093 socket->error = netconn_bind(socket->sock, socket->local_addr, socket->port); 00094 if(socket->error != ERR_OK) 00095 { 00096 LOG_ERR("Connection error\n"); 00097 goto error; 00098 } 00099 00100 socket->error = netconn_connect(socket->sock, socket->remote_addr, socket->port); 00101 if(socket->error != ERR_OK) 00102 { 00103 LOG_ERR("Cannot create socket\n"); 00104 goto error; 00105 } 00106 00107 LOG_INFO("connected ip=%d.%d.%d.%d\n", IP_ADDR_TO_INT_TUPLE(socket->remote_addr->addr)); 00108 return true; 00109 00110 error: 00111 netconn_delete(socket->sock); 00112 socket->sock = NULL; 00113 return false; 00114 } 00115 00116 static int tcpsocket_close(KFile *fd) 00117 { 00118 TcpSocket *socket = TCPSOCKET_CAST(fd); 00119 close_socket(socket); 00120 socket->error = 0; 00121 return 0; 00122 } 00123 00124 static KFile *tcpsocket_reopen(KFile *fd) 00125 { 00126 TcpSocket *socket = TCPSOCKET_CAST(fd); 00127 if (tcpsocket_reconnect(socket)) 00128 return fd; 00129 00130 return NULL; 00131 } 00132 00133 /* 00134 * Read data from socket. 00135 * 00136 * The read return the bytes that had been received if they are less than we request too. 00137 * Otherwise if the byte that we want read are less that the received bytes, we return only 00138 * the requested bytes. To get the remaning bytes we need to make an others read, until the 00139 * buffer is empty. 00140 * When there are not any more bytes, a new read takes data from remote socket. 00141 */ 00142 static size_t tcpsocket_read(KFile *fd, void *buf, size_t len) 00143 { 00144 TcpSocket *socket = TCPSOCKET_CAST(fd); 00145 00146 char *data; 00147 uint16_t read_len = 0; 00148 00149 if (socket->remaning_data_len <= 0) 00150 { 00151 LOG_INFO("No byte left.\n"); 00152 netbuf_delete(socket->rx_buf_conn); 00153 } 00154 else /* We had byte into buffer use that */ 00155 { 00156 LOG_INFO("Read stored bytes.\n"); 00157 if (!socket->rx_buf_conn) 00158 { 00159 LOG_ERR("Byte stored are corrupted!\n"); 00160 socket->remaning_data_len = 0; 00161 return 0; 00162 } 00163 uint16_t tot_data_len = 0; 00164 netbuf_data(socket->rx_buf_conn, (void **)&data, &tot_data_len); 00165 00166 if (data) 00167 { 00168 ASSERT(((int)tot_data_len - (int)socket->remaning_data_len) >= 0); 00169 size_t chunk_len = MIN((size_t)(socket->remaning_data_len), len); 00170 memcpy((char *)buf, &data[tot_data_len - socket->remaning_data_len], chunk_len); 00171 00172 socket->remaning_data_len -= chunk_len; 00173 return chunk_len; 00174 } 00175 else 00176 { 00177 LOG_ERR("No valid data to read\n"); 00178 socket->remaning_data_len = 0; 00179 netbuf_delete(socket->rx_buf_conn); 00180 return 0; 00181 } 00182 } 00183 00184 /* Try reconnecting if our socket isn't valid */ 00185 if ((socket->sock == NULL) && !tcpsocket_reconnect(socket)) 00186 return 0; 00187 00188 while (len) 00189 { 00190 LOG_INFO("Get bytes from socket.\n"); 00191 socket->rx_buf_conn = netconn_recv(socket->sock); 00192 00193 socket->error = netconn_err(socket->sock); 00194 if (socket->error != ERR_OK) 00195 { 00196 LOG_ERR("While recv %d\n", socket->error); 00197 close_socket(socket); 00198 return 0; 00199 } 00200 00201 size_t chunk_len = 0; 00202 uint16_t data_len = 0; 00203 if (socket->rx_buf_conn) 00204 { 00205 netbuf_data(socket->rx_buf_conn, (void **)&data, &data_len); 00206 00207 if (data) 00208 { 00209 chunk_len = MIN((size_t)data_len, len); 00210 memcpy(buf, data, chunk_len); 00211 00212 socket->remaning_data_len = data_len - chunk_len; 00213 } 00214 00215 if (socket->remaning_data_len <= 0) 00216 { 00217 netbuf_delete(socket->rx_buf_conn); 00218 socket->rx_buf_conn = NULL; 00219 socket->remaning_data_len = 0; 00220 return chunk_len; 00221 } 00222 } 00223 00224 len -= chunk_len; 00225 read_len += chunk_len; 00226 } 00227 00228 return read_len; 00229 } 00230 00231 static size_t tcpsocket_write(KFile *fd, const void *buf, size_t len) 00232 { 00233 TcpSocket *socket = TCPSOCKET_CAST(fd); 00234 00235 /* Try reconnecting if our socket isn't valid */ 00236 if ((socket->sock == NULL) && !tcpsocket_reconnect(socket)) 00237 return 0; 00238 00239 socket->error = netconn_write(socket->sock, buf, len, NETCONN_COPY); 00240 if (socket->error != ERR_OK) 00241 { 00242 LOG_ERR("While writing %d\n", socket->error); 00243 close_socket(socket); 00244 return 0; 00245 } 00246 00247 return len; 00248 } 00249 00250 static int tcpsocket_error(KFile *fd) 00251 { 00252 TcpSocket *socket = TCPSOCKET_CAST(fd); 00253 return socket->error; 00254 } 00255 00256 static void tcpsocket_clearerr(KFile *fd) 00257 { 00258 TcpSocket *socket = TCPSOCKET_CAST(fd); 00259 socket->error = 0; 00260 } 00261 00262 00269 void tcpsocket_serverPoll(KFile *fd) 00270 { 00271 TcpSocket *socket = TCPSOCKET_CAST(fd); 00272 00273 if (!socket->sock) 00274 socket->sock = netconn_accept(socket->server_sock); 00275 00276 if (!socket->sock) 00277 { 00278 LOG_ERR("Unable to connect with client\n"); 00279 return; 00280 } 00281 00282 socket->handler(fd); 00283 } 00284 00297 void tcpsocket_init(TcpSocket *socket, struct ip_addr *local_addr, struct ip_addr *remote_addr, uint16_t port) 00298 { 00299 memset(socket, 0, sizeof(TcpSocket)); 00300 00301 socket->local_addr = local_addr; 00302 socket->remote_addr = remote_addr; 00303 socket->port = port; 00304 00305 socket->fd._type = KFT_TCPSOCKET; 00306 socket->fd.read = tcpsocket_read; 00307 socket->fd.error = tcpsocket_error; 00308 socket->fd.close = tcpsocket_close; 00309 socket->fd.write = tcpsocket_write; 00310 socket->fd.clearerr = tcpsocket_clearerr; 00311 socket->fd.reopen = tcpsocket_reopen; 00312 00313 } 00314 00331 void tcpsocket_serverInit(TcpSocket *socket, struct ip_addr *local_addr, struct ip_addr *listen_addr, uint16_t port, tcphandler_t handler) 00332 { 00333 tcpsocket_init(socket, local_addr, listen_addr, port); 00334 socket->handler = handler; 00335 00336 socket->server_sock = netconn_new(NETCONN_TCP); 00337 socket->error = netconn_bind(socket->server_sock, listen_addr, port); 00338 socket->error = netconn_listen(socket->server_sock); 00339 00340 if(socket->error != ERR_OK) 00341 LOG_ERR("Init server\n"); 00342 }
![(please configure the [header_logo] section in trac.ini)](/chrome/site/bertos_logo.png)