00001
00010
00011
00012 #include "urg_c/urg_detect_os.h"
00013 #include <string.h>
00014 #if defined(URG_WINDOWS_OS)
00015 #else
00016 #include <unistd.h>
00017 #include <fcntl.h>
00018 #include <errno.h>
00019 #endif
00020 #include "urg_c/urg_tcpclient.h"
00021
00022 #include <stdio.h>
00023
00024 enum {
00025 Invalid_desc = -1,
00026 };
00027
00028
00029 static void tcpclient_buffer_init(urg_tcpclient_t* cli)
00030 {
00031 ring_initialize(&cli->rb, cli->buf, RB_BITSHIFT);
00032 }
00033
00034
00035
00036 static int tcpclient_buffer_data_num(urg_tcpclient_t* cli)
00037 {
00038 return ring_size(&cli->rb);
00039 }
00040
00041
00042 static int tcpclient_buffer_write(urg_tcpclient_t* cli,
00043 const char* data, int size)
00044 {
00045 return ring_write(&cli->rb, data, size);
00046 }
00047
00048
00049 static int tcpclient_buffer_read(urg_tcpclient_t* cli, char* data, int size)
00050 {
00051 return ring_read(&cli->rb, data, size);
00052 }
00053
00054
00055 static void set_block_mode(urg_tcpclient_t* cli)
00056 {
00057 #if defined(URG_WINDOWS_OS)
00058 u_long flag = 0;
00059 ioctlsocket(cli->sock_desc, FIONBIO, &flag);
00060 #else
00061 int flag = 0;
00062 fcntl(cli->sock_desc, F_SETFL, flag);
00063 #endif
00064 }
00065
00066
00067 int tcpclient_open(urg_tcpclient_t* cli, const char* ip_str, int port_num)
00068 {
00069 enum { Connect_timeout_second = 2 };
00070 fd_set rmask, wmask;
00071 struct timeval tv = { Connect_timeout_second, 0 };
00072 #if defined(URG_WINDOWS_OS)
00073 u_long flag;
00074 #else
00075 int flag;
00076 int sock_optval = -1;
00077 int sock_optval_size = sizeof(sock_optval);
00078 #endif
00079 int ret;
00080
00081 cli->sock_desc = Invalid_desc;
00082 cli->pushed_back = -1;
00083
00084 #if defined(URG_WINDOWS_OS)
00085 {
00086 static int is_initialized = 0;
00087 WORD wVersionRequested = 0x0202;
00088 WSADATA WSAData;
00089 int err;
00090 if (!is_initialized) {
00091 err = WSAStartup(wVersionRequested, &WSAData);
00092 if (err != 0) {
00093 return -1;
00094 }
00095 is_initialized = 1;
00096 }
00097 }
00098 #endif
00099
00100 tcpclient_buffer_init(cli);
00101
00102 cli->sock_addr_size = sizeof (struct sockaddr_in);
00103 if ((cli->sock_desc = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00104 return -1;
00105 }
00106
00107 memset((char*)&(cli->server_addr), 0, sizeof(cli->sock_addr_size));
00108 cli->server_addr.sin_family = AF_INET;
00109 cli->server_addr.sin_port = htons(port_num);
00110
00111 if (!strcmp(ip_str, "localhost")) {
00112 ip_str = "127.0.0.1";
00113 }
00114
00115
00116 if ((cli->server_addr.sin_addr.s_addr = inet_addr(ip_str)) == INADDR_NONE) {
00117 return -1;
00118 }
00119
00120 #if defined(URG_WINDOWS_OS)
00121
00122 flag = 1;
00123 ioctlsocket(cli->sock_desc, FIONBIO, &flag);
00124
00125 if (connect(cli->sock_desc, (const struct sockaddr *)&(cli->server_addr),
00126 cli->sock_addr_size) == SOCKET_ERROR) {
00127 int error_number = WSAGetLastError();
00128 if (error_number != WSAEWOULDBLOCK) {
00129 tcpclient_close(cli);
00130 return -1;
00131 }
00132
00133 FD_ZERO(&rmask);
00134 FD_SET((SOCKET)cli->sock_desc, &rmask);
00135 wmask = rmask;
00136
00137 ret = select((int)cli->sock_desc + 1, &rmask, &wmask, NULL, &tv);
00138 if (ret == 0) {
00139
00140 tcpclient_close(cli);
00141 return -2;
00142 }
00143 }
00144
00145 set_block_mode(cli);
00146
00147 #else
00148
00149 flag = fcntl(cli->sock_desc, F_GETFL, 0);
00150 fcntl(cli->sock_desc, F_SETFL, flag | O_NONBLOCK);
00151
00152 if (connect(cli->sock_desc, (const struct sockaddr *)&(cli->server_addr),
00153 cli->sock_addr_size) < 0) {
00154 if (errno != EINPROGRESS) {
00155 tcpclient_close(cli);
00156 return -1;
00157 }
00158
00159
00160 FD_ZERO(&rmask);
00161 FD_SET(cli->sock_desc, &rmask);
00162 wmask = rmask;
00163
00164 ret = select(cli->sock_desc + 1, &rmask, &wmask, NULL, &tv);
00165 if (ret <= 0) {
00166
00167 tcpclient_close(cli);
00168 return -2;
00169 }
00170
00171 if (getsockopt(cli->sock_desc, SOL_SOCKET, SO_ERROR, (int*)&sock_optval,
00172 (socklen_t*)&sock_optval_size) != 0) {
00173
00174 tcpclient_close(cli);
00175 return -3;
00176 }
00177
00178 if (sock_optval != 0) {
00179
00180 tcpclient_close(cli);
00181 return -4;
00182 }
00183
00184 set_block_mode(cli);
00185 }
00186 #endif
00187
00188 return 0;
00189 }
00190
00191
00192 void tcpclient_close(urg_tcpclient_t* cli)
00193 {
00194 if (cli->sock_desc != Invalid_desc) {
00195 #if defined(URG_WINDOWS_OS)
00196 closesocket(cli->sock_desc);
00197
00198 #else
00199 close(cli->sock_desc);
00200 #endif
00201 cli->sock_desc = Invalid_desc;
00202 }
00203 }
00204
00205
00206 int tcpclient_read(urg_tcpclient_t* cli,
00207 char* userbuf, int req_size, int timeout)
00208 {
00209
00210 int num_in_buf = tcpclient_buffer_data_num(cli);
00211 int sock = cli->sock_desc;
00212 int rem_size = req_size;
00213 int n;
00214
00215
00216 if (num_in_buf > 0) {
00217 n = tcpclient_buffer_read(cli, userbuf, req_size);
00218 rem_size = req_size - n;
00219 if (rem_size <= 0) {
00220 return req_size;
00221 }
00222
00223 num_in_buf = tcpclient_buffer_data_num(cli);
00224 }
00225
00226
00227
00228 {
00229 char tmpbuf[BUFSIZE];
00230
00231 #if defined(URG_WINDOWS_OS)
00232 int no_timeout = 1;
00233 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&no_timeout, sizeof(struct timeval));
00234 n = recv(sock, tmpbuf, BUFSIZE - num_in_buf, 0);
00235 #else
00236 n = recv(sock, tmpbuf, BUFSIZE - num_in_buf, MSG_DONTWAIT);
00237 #endif
00238 if (n > 0) {
00239 tcpclient_buffer_write(cli, tmpbuf, n);
00240 }
00241
00242 n = tcpclient_buffer_read(cli, &userbuf[req_size-rem_size], rem_size);
00243
00244 rem_size -= n;
00245 if (rem_size <= 0) {
00246 return req_size;
00247 }
00248 }
00249
00250
00251 {
00252 #if defined(URG_WINDOWS_OS)
00253 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
00254 (const char *)&timeout, sizeof(struct timeval));
00255 #else
00256 struct timeval tv;
00257 tv.tv_sec = timeout / 1000;
00258 tv.tv_usec = (timeout % 1000) * 1000;
00259 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
00260 #endif
00261
00262 n = recv(sock, &userbuf[req_size-rem_size], rem_size, 0);
00263
00264 if (n > 0) {
00265 rem_size -= n;
00266 }
00267 }
00268
00269 return (req_size - rem_size);
00270 }
00271
00272
00273 int tcpclient_write(urg_tcpclient_t* cli, const char* buf, int size)
00274 {
00275
00276 return send(cli->sock_desc, buf, size, 0);
00277 }
00278
00279
00280 int tcpclient_error(urg_tcpclient_t* cli, char* error_message, int max_size)
00281 {
00282 (void)cli;
00283 (void)error_message;
00284 (void)max_size;
00285
00286
00287
00288 return -1;
00289 }
00290
00291
00292 int tcpclient_readline(urg_tcpclient_t* cli,
00293 char* userbuf, int buf_size, int timeout)
00294 {
00295 int n = 0;
00296 int i = 0;
00297
00298 if (cli->pushed_back > 0) {
00299 userbuf[i] = cli->pushed_back;
00300 i++;
00301 cli->pushed_back = -1;
00302 }
00303 for (; i < buf_size; ++i) {
00304 char ch;
00305 n = tcpclient_read(cli, &ch, 1, timeout);
00306 if (n <= 0) {
00307 break;
00308 }
00309 if (ch == '\n' || ch == '\r') {
00310 break;
00311 }
00312 userbuf[i] = ch;
00313 }
00314
00315 if (i >= buf_size) {
00316 --i;
00317 cli->pushed_back = userbuf[buf_size - 1] & 0xff;
00318 userbuf[buf_size - 1] = '\0';
00319 }
00320 userbuf[i] = '\0';
00321
00322 if (i == 0 && n <= 0) {
00323 return -1;
00324 }
00325
00326 return i;
00327 }