00001
00010 #include "nsds_util.h"
00011 #include "flog.h"
00012
00013 #include <sys/types.h>
00014 #include <sys/socket.h>
00015 #include <netinet/in.h>
00016 #include <arpa/inet.h>
00017 #include <netdb.h>
00018 #include <errno.h>
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <math.h>
00022 #include <unistd.h>
00023 #include <stdint.h>
00024 #include <string.h>
00025 #include <signal.h>
00026 #include <time.h>
00027 #include <sys/time.h>
00028
00029
00030 extern bool control_break;
00031
00032
00033
00046 char *gen_timestamp(void)
00047 {
00048 char me[] = "gen_timestamp";
00049 struct tm l_tm;
00050 struct timeval t_highres;
00051 int rc;
00052 static char timebuf[80];
00053 time_t in_time;
00054
00055
00056 rc = gettimeofday(&t_highres, NULL);
00057 if(rc != 0)
00058 {
00059 flog_usr(FLOG_ERROR, FL_ERR_SYSTEM, me,
00060 "Error reading current time!");
00061 return(NULL);
00062 }
00063
00064
00065 in_time = (time_t) t_highres.tv_sec;
00066
00067
00068 gmtime_r(&in_time, &l_tm);
00069
00070
00071
00072 sprintf(timebuf, "%04d-%02d-%02dT%02d:%02d:%02d.%05.0f",
00073 l_tm.tm_year + 1900,
00074 l_tm.tm_mon + 1,
00075 l_tm.tm_mday,
00076 l_tm.tm_hour,
00077 l_tm.tm_min,
00078 l_tm.tm_sec,
00079 (float) (t_highres.tv_usec / 10.0));
00080
00081 return(timebuf);
00082 }
00083
00084
00100 int tcp_socket_make(const uint16_t SRV_PORT, const int QUEUE_LENGTH)
00101 {
00102 char me[] = "tcp_socket_make";
00103 struct sockaddr_in serv_in;
00104 struct protoent *ppe = NULL;
00105 int itmp;
00106 int new_socket = 0;
00107 const int no_socket = -1;
00108 int so_reuseaddr = 1;
00109 struct linger so_linger;
00110
00111
00112 ppe = getprotobyname("tcp");
00113 if(ppe == NULL)
00114 {
00115 flog_usr(FLOG_ERROR, FL_ERR_SYSTEM, me,
00116 "Error on getprotobyname");
00117 return(no_socket);
00118 }
00119
00120 itmp = socket(PF_INET, SOCK_STREAM, ppe->p_proto);
00121
00122
00123 if(itmp < 0)
00124 {
00125 flog_usr(FLOG_ERROR, FL_ERR_SOCKET, me,
00126 "Error on socket creation; server running?");
00127 return(no_socket);
00128 }
00129 else
00130 new_socket = itmp;
00131
00132
00133 itmp = setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR,
00134 &so_reuseaddr, sizeof(so_reuseaddr));
00135 if(itmp != 0)
00136 flog_usr(FLOG_WARNING, 0, me,
00137 "Failure on setsockopt");
00138
00139
00140 so_linger.l_onoff = true;
00141 so_linger.l_linger = 5;
00142 itmp = setsockopt(new_socket, SOL_SOCKET, SO_LINGER,
00143 &so_linger, sizeof(so_linger));
00144 if(itmp != 0)
00145 flog_usr(FLOG_WARNING, 0, me,
00146 "Failure on setsockopt");
00147
00148
00149 serv_in.sin_family = AF_INET;
00150 serv_in.sin_addr.s_addr = INADDR_ANY;
00151 serv_in.sin_port = htons(SRV_PORT);
00152
00153
00154 itmp = bind(new_socket, (struct sockaddr *) &serv_in, sizeof(serv_in));
00155
00156
00157 if(itmp < 0)
00158 {
00159 flog_usr(FLOG_ERROR, FL_ERR_SOCKET, me,
00160 "Unable to bind to local port; server already running?");
00161
00162 close(new_socket);
00163 return(no_socket);
00164 }
00165
00166
00167
00168
00169 itmp = listen(new_socket, QUEUE_LENGTH);
00170 if(itmp < 0)
00171 {
00172 flog_usr(FLOG_ERROR, FL_ERR_SOCKET, me, "Listen failure");
00173 close(new_socket);
00174
00175 return(no_socket);
00176 }
00177
00178 flog_usr(FLOG_NOTICE, 0, me,
00179 "Network setup completed OK on port %d", SRV_PORT);
00180
00181 return(new_socket);
00182 }
00183
00194 int tcp_nl_write(const int socket, const char *buf)
00195 {
00196 char me[] = "tcp_nl_write";
00197 int rc;
00198 int len = strlen(buf);
00199 char newline[] = "\n";
00200
00201 rc = write(socket, buf, len);
00202 if(rc != len)
00203 {
00204 flog_usr(FLOG_ERROR, FL_ERR_TRANSCEIVE, me,
00205 "Error writing to socket");
00206 return(rc);
00207 }
00208
00209
00210 rc = write(socket, newline, 1);
00211 if(rc != 1)
00212 {
00213 flog_usr(FLOG_ERROR, FL_ERR_TRANSCEIVE, me,
00214 "Error writing newline to socket");
00215 return(rc);
00216 }
00217
00218
00219 fsync(socket);
00220
00221
00222 return(len);
00223 }
00224
00246 int tcp_nl_read(const uint16_t socket, char *buf, const time_t timeout)
00247 {
00248 char me[] = "tcp_nl_read";
00249 int bytes_read = 0;
00250 int rc;
00251 char *write_ptr = buf;
00252 bool done = false;
00253 bool got_newline = false;
00254 socket_wait_ret sel_rc;
00255 bool got_err = false;
00256
00257 if(buf == NULL)
00258 return(-1);
00259
00260
00261 memset(buf, 0x00, MAX_CMD_LEN);
00262
00263 while(!done)
00264 {
00265 sel_rc = SWAIT_SYS_ERR;
00266
00267 if(bytes_read >= (MAX_CMD_LEN - 1))
00268 {
00269 flog_usr(FLOG_ERROR, FL_ERR_BUF_NOSPACE, me,
00270 "Max cmd length %d exceeded with no delimiter",
00271 MAX_CMD_LEN);
00272 done = true;
00273 got_err = true;
00274 break;
00275 }
00276
00277
00278 sel_rc = tcp_socket_wait(socket, timeout);
00279 if(sel_rc == SWAIT_TIMEOUT)
00280 {
00281 flog_usr(FLOG_L3BUG, 0, me, "No data before timeout");
00282 done = true;
00283 break;
00284 }
00285 if(sel_rc != SWAIT_GOT_DATA)
00286 {
00287 flog_usr(FLOG_ERROR, FL_ERR_SOCKET, me, "Error waiting for data");
00288 done = true;
00289 got_err = true;
00290 break;
00291 }
00292
00293
00294 rc = read(socket, write_ptr, 1);
00295 if(rc == 1)
00296 {
00297
00298 if((*write_ptr == '\n') || (*write_ptr == '\r'))
00299 {
00300
00301 if(bytes_read == 0)
00302 {
00303
00304 continue;
00305 }
00306
00307 got_newline = true;
00308 done = true;
00309
00310
00311 *write_ptr = 0x00;
00312
00313 break;
00314 }
00315 else
00316 {
00317 write_ptr++;
00318 bytes_read++;
00319 }
00320
00321 }
00322 else if(rc <= 0)
00323 {
00324 done = true;
00325 got_err = true;
00326 break;
00327 }
00328 else
00329 usleep(10);
00330 }
00331
00332
00333
00334
00335 if(got_newline)
00336 return(bytes_read);
00337 else if(got_err == false)
00338 return(0);
00339 else
00340 return(-1);
00341 }
00342
00343
00359 int tcp_connect(const char *server, const uint16_t port)
00360 {
00361 char me[] = "tcp_connect";
00362 struct hostent *phe;
00363 struct protoent *ppe;
00364 struct sockaddr_in sin;
00365 int s, type;
00366 struct linger so_linger;
00367 int itmp;
00368
00369
00370 memset(&sin, 0x00, sizeof(sin));
00371
00372
00373 sin.sin_family = AF_INET;
00374
00375
00376 sin.sin_port = htons(port);
00377
00378
00379 phe = gethostbyname(server);
00380
00381 if(phe != NULL)
00382 memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
00383 else
00384 {
00385 flog_usr(FLOG_ERROR, FL_ERR_HOST_NOTFOUND, me,
00386 "Connection error in gethostbyname");
00387 return(-1);
00388 }
00389
00390
00391 if ( (ppe = getprotobyname("tcp")) == 0)
00392 {
00393 flog_usr(FLOG_ERROR, FL_ERR_SYSTEM, me,
00394 "Connection error in getprotobyname");
00395 return(-2);
00396 }
00397
00398 type = SOCK_STREAM;
00399
00400
00401 s = socket(PF_INET, type, ppe->p_proto);
00402 if (s < 0)
00403 {
00404 flog_usr(FLOG_ERROR, FL_ERR_SYSTEM, me, "Error allocating socket");
00405 return(-3);
00406 }
00407
00408
00409 so_linger.l_onoff = true;
00410 so_linger.l_linger = 5;
00411 itmp = setsockopt(s, SOL_SOCKET, SO_LINGER,
00412 &so_linger, sizeof(so_linger));
00413 if(itmp != 0)
00414 flog_usr(FLOG_WARNING, FL_ERR_SOCKET, me,
00415 "Error setting socket opts");
00416
00417
00418 if(connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
00419 return(-1);
00420
00421 return s;
00422 }
00423
00424
00437 socket_wait_ret tcp_socket_wait(const int socket, const time_t timeout)
00438 {
00439 char me[] = "tcp_socket_wait";
00440 fd_set read_fds;
00441 fd_set err_fds;
00442 struct timeval *sel_timeout = NULL;
00443 int num_fds;
00444 int sel_return;
00445 struct timeval foo;
00446
00447
00448
00449 if(timeout > 0)
00450 {
00451 sel_timeout = (struct timeval *) &foo;
00452
00453 sel_timeout->tv_sec = timeout;
00454 sel_timeout->tv_usec = 0L;
00455 }
00456 else
00457 sel_timeout = NULL;
00458
00459
00460 FD_ZERO(&read_fds);
00461 FD_ZERO(&err_fds);
00462
00463
00464 FD_SET(socket, &read_fds);
00465 FD_SET(socket, &err_fds);
00466
00467
00468 num_fds = getdtablesize();
00469
00470
00471 sel_return = select(num_fds, &read_fds,
00472 NULL, &err_fds, sel_timeout);
00473
00474
00475 if(FD_ISSET(socket, &err_fds))
00476 {
00477 flog_usr(FLOG_INFO, FL_ERR_SOCKET, me,
00478 "Error bit set in select");
00479 return(SWAIT_SYS_ERR);
00480 }
00481
00482
00483 if((sel_return > 0) && (FD_ISSET(socket, &read_fds)))
00484 return(SWAIT_GOT_DATA);
00485
00486 if(sel_return == -1)
00487 {
00488 flog_usr(FLOG_INFO, FL_ERR_SOCKET, me, "select returns -1");
00489 return(SWAIT_SYS_ERR);
00490 }
00491
00492 if(sel_return == 0)
00493 return(SWAIT_TIMEOUT);
00494
00495
00496 flog_usr(FLOG_L3BUG, 0, me,
00497 "Select returned %d, errno=%d", sel_return, errno);
00498 return(SWAIT_SYS_ERR);
00499 }
00500
00501
00510 char * tcp_peername(const int socket)
00511 {
00512 char me[] = "tcp_peername";
00513 int itmp, rc;
00514 struct sockaddr client_info;
00515 struct sockaddr_in *so = (struct sockaddr_in *) &client_info;
00516 struct hostent *cl_hostent = NULL;
00517 static char remote_hostname[128] = "";
00518
00519
00520
00521 itmp = sizeof(struct sockaddr);
00522 rc = getpeername(socket, &client_info, &itmp);
00523 if((rc != 0) || (itmp < 0))
00524 {
00525 flog_usr(FLOG_ERROR, FL_ERR_HOST_NOTFOUND, me,
00526 "Error getting peer information");
00527 return(remote_hostname);
00528 }
00529
00530
00531 cl_hostent = gethostbyaddr((char *) &so->sin_addr.s_addr,
00532 sizeof(so->sin_addr.s_addr), AF_INET);
00533 if(cl_hostent == NULL)
00534 {
00535 flog_usr(FLOG_ERROR, FL_ERR_HOST_NOTFOUND, me,
00536 "Reverse DNS lookup failed");
00537 strcpy(remote_hostname, inet_ntoa(so->sin_addr));
00538 }
00539 else
00540 strcpy(remote_hostname, cl_hostent->h_name);
00541
00542 return(remote_hostname);
00543 }
00544
00545
00546
00547
00562 int tcp_connect_retry(const char *host, const uint16_t port,
00563 const time_t retry_delay, const time_t end_time,
00564 const char *description)
00565 {
00566 char me[] = "tcp_connect_retry";
00567 bool done = false;
00568 int retry_count = 0;
00569 int cl_socket = -1;
00570 const char *desc = NULL;
00571
00572
00573
00574 if(description != NULL)
00575 desc = description;
00576 else
00577 desc = host;
00578
00579 while((done == false) && !(control_break))
00580 {
00581
00582 if((end_time > 0) && (time(NULL) >= end_time))
00583 {
00584 flog_usr(FLOG_L3BUG, 0, me,
00585 "End time reached without connection, exiting");
00586
00587 done = true;
00588 break;
00589 }
00590
00591 flog_usr(FLOG_L2BUG, 0, me,
00592 "Connecting to %s on %s, port %d", desc, host, port);
00593
00594 cl_socket = tcp_connect(host, port);
00595 if(cl_socket > 0)
00596 {
00597 done = true;
00598 break;
00599 }
00600
00601 flog_usr(FLOG_CL2BUG, 0, me,
00602 "Unable to connect to %s on %s, sleeping %d seconds",
00603 desc, host, (int) retry_delay);
00604
00605 retry_count++;
00606 sleep(retry_delay);
00607 }
00608
00609 return(cl_socket);
00610 }
00611
00612
00620 void tcp_close(const int socket_fd)
00621 {
00622 if(socket_fd <= 0)
00623 return;
00624
00625
00626 shutdown(socket_fd, SHUT_RDWR);
00627 close(socket_fd);
00628
00629 return;
00630 }