00001
00025 #include "stdint.h"
00026 #include <string.h>
00027
00028 #if defined(_USE_WIN_API)
00029 #include <winsock2.h>
00030 #include <mstcpip.h>
00031 #pragma comment(lib, "wsock32.lib")
00032 #elif defined(_USE_LINUX_API)
00033 #include <arpa/inet.h>
00034 #include <errno.h>
00035 #include <fcntl.h>
00036 #include <netinet/tcp.h>
00037 #include <sys/socket.h>
00038 #else
00039 #include "dn_additional.h"
00040 #endif
00041
00042 #include "dn_common.h"
00043 #include "dn_device.h"
00044 #include "dn_socket.h"
00045 #include "dn_tcp.h"
00046
00047 uint32_t tcp_conn_timeout;
00048
00049 #if defined(_USE_WIN_API)
00050 static HRESULT _tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
00051 {
00052 int ret;
00053 DWORD dwBytes;
00054 struct tcp_keepalive stParameter =
00055 { 0}, stReturned =
00056 { 0};
00057
00058 stParameter.onoff = (enable != 0) ? 1: 0;
00059 stParameter.keepalivetime = (idle == 0) ? 1 : (idle * 1000);
00060 stParameter.keepaliveinterval = interval * 1000;
00061 ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &stParameter, sizeof(stParameter), &stReturned, sizeof(stReturned), &dwBytes, NULL, NULL);
00062
00063 return (ret == SOCKET_ERROR) ? OSERR2HRESULT(ret) : S_OK;
00064 }
00065 #elif defined(_USE_LINUX_API)
00066 static HRESULT _tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval, uint32_t count)
00067 {
00068 int ret;
00069
00070 enable = (enable != 0) ? 1: 0;
00071 ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&enable, sizeof(enable));
00072 if(ret < 0) {
00073 ret = DNGetLastError();
00074 return OSERR2HRESULT(ret);
00075 }
00076
00077 idle = (idle == 0) ? 1 : idle;
00078 ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&idle, sizeof(idle));
00079 if(ret < 0) {
00080 ret = DNGetLastError();
00081 return OSERR2HRESULT(ret);
00082 }
00083
00084 ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, (char *)&interval, sizeof(interval));
00085 if(ret < 0) {
00086 ret = DNGetLastError();
00087 return OSERR2HRESULT(ret);
00088 }
00089
00090 ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, (char *)&count, sizeof(count));
00091 if(ret < 0) {
00092 ret = DNGetLastError();
00093 return OSERR2HRESULT(ret);
00094 }
00095
00096 return S_OK;
00097 }
00098 #endif
00099
00106 HRESULT
00107 tcp_open_client(void *param, int *sock)
00108 {
00109 int ret;
00110 HRESULT hr;
00111 struct sockaddr_in server;
00112 const struct CONN_PARAM_ETH *eth_param = (const struct CONN_PARAM_ETH *) param;
00113 #if defined(_USE_WIN_API)
00114 WSAEVENT connevt = NULL;
00115 WSANETWORKEVENTS events;
00116 #else
00117 int funcval = 0;
00118 fd_set fds;
00119 struct timeval tv;
00120 #endif
00121
00122 if (param == NULL || sock == NULL) {
00123 hr = E_INVALIDARG;
00124 goto exit_proc;
00125 }
00126
00127 hr = socket_open(SOCK_STREAM, sock);
00128 if (FAILED(hr)) {
00129 goto exit_proc;
00130 }
00131
00132 memset(&server, 0, sizeof(server));
00133 server.sin_addr.s_addr = eth_param->dst_addr;
00134 server.sin_port = eth_param->dst_port;
00135 server.sin_family = AF_INET;
00136
00137 if(tcp_conn_timeout > 0) {
00138 #if defined(_USE_WIN_API)
00139 connevt = WSACreateEvent();
00140 if(connevt == WSA_INVALID_EVENT) {
00141 hr = OSERR2HRESULT(WSAGetLastError());
00142 goto exit_proc;
00143 }
00144 ret = WSAEventSelect(*sock, connevt, FD_CONNECT);
00145 if(ret == SOCKET_ERROR) {
00146 hr = OSERR2HRESULT(WSAGetLastError());
00147 goto exit_proc;
00148 }
00149 #else
00150 funcval = fcntl(*sock, F_GETFL, 0);
00151 if(funcval < 0) {
00152 hr = OSERR2HRESULT(DNGetLastError());
00153 goto exit_proc;
00154 }
00155 ret = fcntl(*sock, F_SETFL, funcval | O_NONBLOCK);
00156 if(ret < 0) {
00157 hr = OSERR2HRESULT(DNGetLastError());
00158 goto exit_proc;
00159 }
00160 #endif
00161 }
00162
00163 ret = connect(*sock, (struct sockaddr *) &server, sizeof(server));
00164 if (ret < 0) {
00165 #if defined(_USE_WIN_API)
00166 ret = WSAGetLastError();
00167 if(ret != WSAEWOULDBLOCK) {
00168 hr = OSERR2HRESULT(ret);
00169 goto exit_proc;
00170 }
00171
00172 ret = WSAWaitForMultipleEvents(1, &connevt,
00173 FALSE, tcp_conn_timeout, FALSE);
00174 if (ret != WSA_WAIT_EVENT_0) {
00175 if (ret == WSA_WAIT_TIMEOUT) {
00176 hr = E_TIMEOUT;
00177 } else {
00178 hr = OSERR2HRESULT(WSAGetLastError());
00179 }
00180 goto exit_proc;
00181 }
00182
00183 ret = WSAEnumNetworkEvents(*sock, connevt, &events);
00184 if (ret == SOCKET_ERROR) {
00185 hr = OSERR2HRESULT(WSAGetLastError());
00186 goto exit_proc;
00187 }
00188 if (!(events.lNetworkEvents & FD_CONNECT)) {
00189 hr = E_FAIL;
00190 goto exit_proc;
00191 }
00192 if (events.iErrorCode[FD_CONNECT_BIT] != 0) {
00193 hr = OSERR2HRESULT(events.iErrorCode[FD_CONNECT_BIT]);
00194 goto exit_proc;
00195 }
00196 #else
00197 ret = DNGetLastError();
00198 if (ret != EINPROGRESS) {
00199 hr = OSERR2HRESULT(ret);
00200 goto exit_proc;
00201 }
00202
00203 FD_ZERO(&fds);
00204 FD_SET(*sock, &fds);
00205
00206 tv.tv_sec = tcp_conn_timeout / 1000;
00207 tv.tv_usec = (tcp_conn_timeout % 1000) * 1000;
00208
00209 ret = select(*sock + 1, NULL, &fds, NULL, &tv);
00210 if (ret == 0) {
00211 hr = E_TIMEOUT;
00212 goto exit_proc;
00213 }
00214 else if (ret < 0) {
00215 ret = DNGetLastError();
00216 hr = OSERR2HRESULT(ret);
00217 goto exit_proc;
00218 }
00219 #endif
00220 }
00221
00222 exit_proc:
00223 if((sock != NULL) && (*sock != 0)) {
00224 #if defined(_USE_WIN_API)
00225 DWORD dwTemp = 0;
00226 WSAEventSelect(*sock, NULL, 0);
00227 ioctlsocket(*sock, FIONBIO, &dwTemp);
00228
00229 if(connevt != NULL) {
00230 WSACloseEvent(connevt);
00231 }
00232 #else
00233 fcntl(*sock, F_SETFL, funcval & ~O_NONBLOCK);
00234 #endif
00235
00236 if(FAILED(hr)) {
00237 socket_close(sock);
00238 }
00239 }
00240
00241
00242 tcp_conn_timeout = 0;
00243
00244 return hr;
00245 }
00246
00253 HRESULT
00254 tcp_open_server(void *param, int *sock)
00255 {
00256 int ret, flag;
00257 HRESULT hr;
00258 const struct CONN_PARAM_ETH *eth_param = (const struct CONN_PARAM_ETH *) param;
00259
00260 if (param == NULL || sock == NULL)
00261 return E_INVALIDARG;
00262
00263 if (eth_param->src_port == 0)
00264 return E_INVALIDARG;
00265
00266 hr = socket_open(SOCK_STREAM, sock);
00267 if (FAILED(hr))
00268 return hr;
00269
00270
00271 flag = 1;
00272 ret = setsockopt(*sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag,
00273 sizeof(flag));
00274 if (ret < 0) {
00275 ret = DNGetLastError();
00276 socket_close(sock);
00277 return OSERR2HRESULT(ret);
00278 }
00279
00280
00281 hr = socket_bind(eth_param, sock);
00282 if (FAILED(hr)) {
00283 socket_close(sock);
00284 return hr;
00285 }
00286
00287 if (SUCCEEDED(hr)) {
00288 ret = listen(*sock, 1);
00289 if (ret < 0) {
00290 ret = DNGetLastError();
00291 socket_close(sock);
00292 hr = OSERR2HRESULT(ret);
00293 }
00294 }
00295
00296 return hr;
00297 }
00298
00304 HRESULT
00305 tcp_close(int *sock)
00306 {
00307 return socket_close(sock);
00308 }
00309
00318 HRESULT
00319 tcp_send(int sock, const char *buf, uint32_t len_buf, void *arg)
00320 {
00321 int ret, flag = 0;
00322 uint32_t len_send, len_sended;
00323
00324 if (sock <= 0)
00325 return E_HANDLE;
00326 if (buf == NULL || strlen(buf) == 0)
00327 return E_INVALIDARG;
00328
00329 #ifdef MSG_NOSIGNAL
00330 flag |= MSG_NOSIGNAL;
00331 #endif
00332
00333 if (arg != NULL) {
00334 flag |= *(int *) arg;
00335 }
00336
00337 len_send = (len_buf != 0) ? len_buf : strlen(buf);
00338
00339 ret = send(sock, buf, len_send, flag);
00340 len_sended = ret;
00341
00342 if (ret < 0) {
00343 ret = DNGetLastError();
00344 return OSERR2HRESULT(ret);
00345 }
00346
00347 if (len_send > len_sended) {
00348 return E_TIMEOUT;
00349 }
00350
00351 return S_OK;
00352 }
00353
00363 HRESULT
00364 tcp_recv(int sock, char *buf, uint32_t len_buf, uint32_t *len_recved,
00365 uint32_t timeout, void *arg)
00366 {
00367 int ret, flag = 0;
00368 HRESULT hr;
00369
00370 if (sock <= 0)
00371 return E_HANDLE;
00372 if (buf == NULL || len_recved == NULL)
00373 return E_INVALIDARG;
00374
00375 if (arg != NULL) {
00376 flag |= *(int *) arg;
00377 }
00378
00379 hr = check_timeout(sock, timeout);
00380 if (FAILED(hr))
00381 return hr;
00382
00383 ret = recv(sock, buf, len_buf, flag);
00384 *len_recved = ret;
00385
00386 if (ret < 0) {
00387 ret = DNGetLastError();
00388 return OSERR2HRESULT(ret);
00389 }
00390
00391 if (*len_recved == 0) {
00392 return E_ACCESSDENIED;
00393 }
00394
00395 return S_OK;
00396 }
00397
00404 HRESULT
00405 tcp_set_timeout(int sock, uint32_t timeout)
00406 {
00407 return socket_set_timeout(sock, timeout);
00408 }
00409
00416 HRESULT
00417 tcp_clear(int sock, uint32_t timeout)
00418 {
00419 uint32_t len_recv = DEV_BUF_MAX, len_recved;
00420 char buf_tmp[DEV_BUF_MAX];
00421 HRESULT hr;
00422
00423 if (sock <= 0)
00424 return E_HANDLE;
00425
00426 hr = tcp_set_timeout(sock, 0);
00427 if (FAILED(hr))
00428 return hr;
00429
00430 do {
00431 hr = tcp_recv(sock, buf_tmp, len_recv, &len_recved, 0, NULL);
00432 } while (SUCCEEDED(hr));
00433
00434 hr = tcp_set_timeout(sock, timeout);
00435
00436 return hr;
00437 }
00438
00447 HRESULT
00448 tcp_accept(int sock, int *client)
00449 {
00450 int ret;
00451 extern int socket_counter;
00452 HRESULT hr;
00453
00454 if (sock <= 0)
00455 return E_HANDLE;
00456 if (client == NULL)
00457 return E_INVALIDARG;
00458
00459 hr = check_timeout(sock, 0);
00460 if (FAILED(hr))
00461 return hr;
00462
00463 *client = accept(sock, NULL, NULL);
00464 if (*client < 0) {
00465 *client = 0;
00466 ret = DNGetLastError();
00467 return OSERR2HRESULT(ret);
00468 }
00469
00470 socket_counter++;
00471
00472 return hr;
00473 }
00474
00484 HRESULT
00485 tcp_set_keepalive(int sock, int enable, uint32_t idle, uint32_t interval,
00486 uint32_t count)
00487 {
00488 if (sock <= 0)
00489 return E_HANDLE;
00490 return _tcp_set_keepalive(sock, enable, idle, interval, count);
00491 }
00492
00499 HRESULT
00500 tcp_set_nodelay(int sock, int enable)
00501 {
00502 int ret;
00503
00504 if (sock <= 0)
00505 return E_HANDLE;
00506
00507 enable = (enable != 0) ? 1 : 0;
00508 ret = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &enable,
00509 sizeof(enable));
00510 if (ret < 0) {
00511 ret = DNGetLastError();
00512 return OSERR2HRESULT(ret);
00513 }
00514
00515 return S_OK;
00516 }