Changeset 5eae97a for lib/trace.c
- Timestamp:
- 07/26/05 14:58:21 (17 years ago)
- Branches:
- 4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
- Children:
- dd6e168
- Parents:
- 8c749ae5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/trace.c
rdb06c9d r5eae97a 132 132 #endif 133 133 134 #include <err.h> 134 135 135 136 typedef enum {SOCKET, TRACE, STDIN, DEVICE, INTERFACE, RT } source_t; … … 137 138 typedef enum {ERF, PCAP, PCAPINT, DAG, RTCLIENT, WAG, WAGINT } format_t; 138 139 140 typedef enum {RTSERVER, GZERF } output_t; 139 141 #if HAVE_BPF 140 142 /** A type encapsulating a bpf filter … … 149 151 #endif 150 152 153 struct libtrace_out_t { 154 output_t outputformat; 155 156 union { 157 struct { 158 char *hostname; 159 short port; 160 } rt; 161 char *path; 162 char *interface; 163 } conn_info; 164 165 union { 166 int fd; 167 #if HAVE_ZLIB 168 gzFile *file; 169 #else 170 FILE *file; 171 #endif 172 #if HAVE_PCAP 173 pcap_t *pcap; 174 #endif 175 } output; 176 177 struct fifo_t *fifo; 178 }; 179 151 180 /** The information about traces that are open 152 181 * @internal … … 155 184 format_t format; /**< The format that this trace is in */ 156 185 source_t sourcetype; /**< The type (device,file, etc */ 186 157 187 union { 158 188 /** Information about rtclients */ … … 177 207 #endif 178 208 } input; 179 struct fifo_t *fifo; 209 210 struct fifo_t *fifo; 180 211 struct { 181 212 void *buf; … … 393 424 } 394 425 426 /** Initialises the data contained within the libtrace_out_t structure, based on the provided uri. 427 * 428 * @param libtrace the libtrace_out_t structure to initialise 429 * @param uri the uri defining the output type and destination 430 * @returns 1 if initialised successfully, 0 otherwise 431 * 432 * @author Shane Alcock 433 * */ 434 static int init_output(struct libtrace_out_t **libtrace, char *uri) { 435 char *scan = calloc(sizeof(char),URI_PROTO_LINE); 436 char *uridata = 0; 437 438 // parse the URI to determine what sort of event we are dealing with 439 440 // want snippet before the : to get the uri base type. 441 442 if((uridata = strchr(uri,':')) == NULL) { 443 // badly formed URI - needs a : 444 return 0; 445 } 446 447 if ((*uridata - *uri) > URI_PROTO_LINE) { 448 // badly formed URI - uri type is too long 449 return 0; 450 } 451 strncpy(scan,uri, (uridata - uri)); 452 453 if (!strncasecmp(scan,"gzerf",5)) { 454 (*libtrace)->outputformat = GZERF; 455 } else if (!strncasecmp(scan, "rt", 2)) { 456 (*libtrace)->outputformat = RTSERVER; 457 } else { 458 return 0; 459 } 460 461 uridata ++; 462 switch((*libtrace)->outputformat) { 463 case GZERF: 464 /* 465 * Acceptable uridata takes the form: 466 * /path/to/file.gz 467 */ 468 (*libtrace)->conn_info.path = strdup(uridata); 469 break; 470 case RTSERVER: 471 /* 472 * Possible uridata formats: 473 * hostname 474 * hostname:port 475 */ 476 if (strlen(uridata) == 0) { 477 (*libtrace)->conn_info.rt.hostname = 478 strdup("localhost"); 479 (*libtrace)->conn_info.rt.port = 480 COLLECTOR_PORT; 481 break; 482 } 483 if ((scan = strchr(uridata,':')) == NULL) { 484 (*libtrace)->conn_info.rt.hostname = 485 strdup(uridata); 486 (*libtrace)->conn_info.rt.port = 487 COLLECTOR_PORT; 488 } else { 489 (*libtrace)->conn_info.rt.hostname = 490 (char *)strndup(uridata,(scan - uridata)); 491 492 (*libtrace)->conn_info.rt.port = 493 atoi(++scan); 494 } 495 break; 496 default: 497 fprintf(stderr, "How did you get here??\n"); 498 } 499 (*libtrace)->fifo = create_fifo(1048576); 500 assert( (*libtrace)->fifo); 501 return 1; 502 } 503 395 504 /** Create a trace file from a URI 396 505 * … … 565 674 } 566 675 676 /** Creates a libtrace_out_t structure and the socket / file through which output will be directed. 677 * 678 * @param uri the uri string describing the output format and the destination 679 * @returns the newly created libtrace_out_t structure 680 * 681 * @author Shane Alcock 682 * */ 683 struct libtrace_out_t *trace_output_create(char *uri) { 684 struct libtrace_out_t *libtrace = malloc(sizeof(struct libtrace_out_t)); 685 struct sockaddr_in remote, client; 686 int client_fd, clilen; 687 struct hostent *he; 688 689 if (init_output(&libtrace, uri) == 0) 690 return 0; 691 692 switch(libtrace->outputformat) { 693 case RTSERVER: 694 if ((he=gethostbyname(libtrace->conn_info.rt.hostname)) == NULL) { 695 perror("gethostbyname"); 696 return 0; 697 } 698 if ((libtrace->output.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 699 perror("socket"); 700 return 0; 701 } 702 // Need to set up a listening server here 703 bzero((char *) &remote, sizeof(remote)); 704 remote.sin_family = AF_INET; 705 remote.sin_addr.s_addr = INADDR_ANY; 706 remote.sin_port = htons(libtrace->conn_info.rt.port); 707 708 if (bind(libtrace->output.fd, (struct sockaddr *) &remote, sizeof(remote)) < 0) { 709 perror("bind"); 710 return 0; 711 } 712 fprintf(stderr, "Waiting for client to connect\n"); 713 714 listen(libtrace->output.fd, 5); 715 clilen = sizeof(client); 716 if ((client_fd = accept(libtrace->output.fd, (struct sockaddr *) &client, &clilen)) < 0) { 717 perror("accept"); 718 return 0; 719 } 720 libtrace->output.fd = client_fd; 721 fprintf(stderr, "Client connected\n"); 722 break; 723 724 725 case GZERF: 726 /* Catch undefined O_LARGEFILE on *BSD etc */ 727 #ifndef O_LARGEFILE 728 # define O_LARGEFILE 0 729 #endif 730 731 #if HAVE_ZLIB 732 // using gzdopen means we can set O_LARGEFILE 733 // ourselves. However, this way is messy and 734 // we lose any error checking on "open" 735 libtrace->output.file = gzdopen(open(libtrace->conn_info.path, O_CREAT | O_LARGEFILE | O_WRONLY, S_IRUSR | S_IWUSR), "w"); 736 #else 737 libtrace->output.file = fdopen(open(libtrace->conn_info.path,O_CREAT | O_LARGEFILE | O_WRONLY, S_IRUSR | S_IWUSR), "w"); 738 #endif 739 if (!libtrace->output.file) { 740 perror("gzdopen (or fdopen)"); 741 return 0; 742 } 743 break; 744 default: 745 fprintf(stderr, "Unrecognised output type - failure to create output instance \n"); 746 exit(0); 747 } 748 return libtrace; 749 } 750 567 751 /** Close a trace file, freeing up any resources it may have been using 568 752 * … … 592 776 destroy_fifo(libtrace->fifo); 593 777 free(libtrace); 778 } 779 780 /** Close an output trace file, freeing up any resources it may have been using 781 * 782 * @param libtrace the output trace file to be destroyed 783 * 784 * @author Shane Alcock 785 * */ 786 void trace_output_destroy(struct libtrace_out_t *libtrace) { 787 assert(libtrace); 788 789 if (libtrace->outputformat == RTSERVER) { 790 close(libtrace->output.fd); 791 } 792 else { 793 #if HAVE_ZLIB 794 gzclose(libtrace->output.file); 795 #else 796 fclose(libtrace->output.file); 797 #endif 798 } 799 destroy_fifo(libtrace->fifo); 800 free(libtrace); 594 801 } 595 802 … … 875 1082 876 1083 assert(size < LIBTRACE_PACKET_BUFSIZE); 877 878 1084 // read in the full packet 879 1085 if ((numbytes = fifo_out_read(libtrace->fifo, buffer, size)) == 0) { … … 898 1104 } 899 1105 1106 static int trace_write(struct libtrace_out_t *libtrace, void *buffer, size_t len) { 1107 int numbytes = 0; 1108 1109 assert(libtrace); 1110 assert(len >= 0); 1111 1112 if (buffer == NULL) { 1113 return 0; 1114 } 1115 1116 while (1) { 1117 switch(libtrace->outputformat) { 1118 case RTSERVER: 1119 #ifndef MSG_NOSIGNAL 1120 #define MSG_NOSIGNAL 0 1121 #endif 1122 // Write to the network 1123 if ((numbytes = send(libtrace->output.fd, 1124 buffer, 1125 len, 1126 MSG_NOSIGNAL)) == -1) { 1127 if (errno == EINTR) { 1128 continue; 1129 } 1130 perror("send"); 1131 return -1; 1132 } 1133 break; 1134 case GZERF: 1135 #if HAVE_ZLIB 1136 if ((numbytes = gzwrite(libtrace->output.file, 1137 buffer, 1138 len)) == -1) { 1139 perror("gzwrite"); 1140 return -1; 1141 } 1142 break; 1143 #else 1144 // Do binary write instead 1145 if ((numbytes = fwrite(buffer, len, 1, libtrace->output.file)) == 0) { 1146 perror("fwrite"); 1147 return -1; 1148 } 1149 break; 1150 #endif 1151 default: 1152 fprintf(stderr, "Bad output type\n"); 1153 break; 1154 } 1155 break; 1156 } 1157 return numbytes; 1158 } 1159 1160 /** Writes a packet to the specified output 1161 * 1162 * @param libtrace describes the output format, destination, etc. 1163 * @param packet the packet to be written out 1164 * @returns the number of bytes written, -1 if write failed 1165 * 1166 * @author Shane Alcock 1167 * */ 1168 int trace_write_packet(struct libtrace_out_t *libtrace, struct libtrace_packet_t *packet) { 1169 // initialise stuff 1170 int numbytes, size; 1171 char buf[RP_BUFSIZE]; 1172 int intsize = sizeof(int); 1173 void *buffer = &buf[intsize]; 1174 int write_required = 0; 1175 1176 assert(libtrace); 1177 assert(packet); 1178 1179 if (libtrace->outputformat == GZERF) { 1180 // do gzwrite 1181 if ((numbytes = gzwrite(libtrace->output.file, packet->buffer, packet->size)) == 0) { 1182 perror("gzwrite"); 1183 return -1; 1184 } 1185 return numbytes; 1186 } 1187 1188 // do fifo stuff for RT output instead 1189 if (libtrace->outputformat == RTSERVER) { 1190 do { 1191 assert(libtrace->fifo); 1192 1193 if (fifo_out_available(libtrace->fifo) == 0 || write_required) { 1194 // Packet added to fifo 1195 if ((numbytes = fifo_write(libtrace->fifo, packet->buffer, packet->size)) == 0) { 1196 // some error with the fifo 1197 perror("fifo_write"); 1198 return -1; 1199 } 1200 write_required = 0; 1201 } 1202 1203 // Read from fifo and add protocol header 1204 if ((numbytes = fifo_out_read(libtrace->fifo, buffer, sizeof(dag_record_t))) == 0) { 1205 // failure reading in from fifo 1206 fifo_out_reset(libtrace->fifo); 1207 write_required = 1; 1208 continue; 1209 } 1210 size = ntohs(((dag_record_t *)buffer)->rlen); 1211 assert(size < LIBTRACE_PACKET_BUFSIZE); 1212 1213 if ((numbytes = fifo_out_read(libtrace->fifo, buffer, size)) == 0) { 1214 // failure reading in from fifo 1215 fifo_out_reset(libtrace->fifo); 1216 write_required = 1; 1217 continue; 1218 } 1219 fifo_out_update(libtrace->fifo, size); 1220 // Sort out the protocol header 1221 memcpy(buf, &packet->status, intsize); 1222 1223 1224 // Send the buffer out on the wire 1225 if ((numbytes = trace_write(libtrace, buf, size + sizeof(int))) <=0 ) { 1226 return numbytes; 1227 } 1228 1229 // Need an ack to come back 1230 // TODO: Obviously this is a little unfinished 1231 if ("ACK_ARRIVES") { 1232 fifo_ack_update(libtrace->fifo, size); 1233 return numbytes; 1234 } else { 1235 fifo_out_reset(libtrace->fifo); 1236 } 1237 } while(1); 1238 } 1239 1240 // Unacceptable output format 1241 fprintf(stderr, "Unknown Output format \n"); 1242 assert(0); 1243 } 900 1244 901 1245 /** get a pointer to the link layer
Note: See TracChangeset
for help on using the changeset viewer.