netsniff-ng: refactor the code a bit
[netsniff-ng.git] / src / mops_sequence.c
blob32e78950edc09d791f50c1bb4c3945f12feb19f2
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
20 #include "mz.h"
21 #include "cli.h"
22 #include "mops.h"
23 #include "llist.h"
26 ///////////////////// TOC /////////////////////
28 // int mops_delete_sequence (char *name)
29 // struct mz_ll * mops_create_sequence (char *name)
30 // int mops_dump_sequence (char* str)
31 // int mops_add_packet_to_sequence (struct mz_ll *seq, struct mops *mp)
32 // int mops_add_delay_to_sequence (struct mz_ll *seq, struct timespec *t)
33 // int mops_delete_packet_from_pseq (struct mz_ll *seq, int index)
34 // int stop_sequence (char *name)
35 // int stop_all_sequences ()
38 // delete one sequence element (from the global packet_sequence list)
39 // which must be specified by its name
40 //
41 int mops_delete_sequence (char *name)
43 struct mz_ll *v;
45 v = mz_ll_search_name (packet_sequences, name);
46 if (v==NULL) return 1; // name not found
48 if (v->state) return 2; // sequence is currently active!
50 if (mz_ll_delete_element (v))
51 return -1; // cannot delete head element!
52 return 0;
57 struct mz_ll * mops_create_sequence (char *name)
59 struct mz_ll *cur;
60 struct pseq *seq;
61 int i;
63 cur = mz_ll_create_new_element(packet_sequences);
64 if (cur==NULL) return NULL;
65 strncpy(cur->name, name, MZ_LL_NAME_LEN);
66 // add data
67 cur->data = (struct pseq*) malloc (sizeof(struct pseq));
68 // initialize data
69 seq = (struct pseq*) cur->data;
70 seq->count = 0;
71 for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
72 seq->packet[i] = NULL; // pointer to the packets
73 seq->gap[i].tv_sec = 0;
74 seq->gap[i].tv_nsec = 0;
76 return cur;
81 // PURPOSE: dumps all sequence objects line-by-line
82 //
83 // ARGUMENTS: Caller must provide a pointer to a string of size MZ_LL_NAME_LEN+(MAX_PACKET_SEQUENCE_LEN*6)
84 // (recommendation: 512 bytes !)
85 //
86 // RETURN VALUE: 0 if list is finished, 1 otherwise
87 //
88 // EXAMPLE: char str[512];
89 // while (mops_dump_sequence(str)
90 // printf("%s\n", str);
91 //
92 int mops_dump_sequence (char* str)
94 static int init=0;
95 static struct mz_ll *cur;
96 struct pseq *seq;
97 struct mops *pkt;
99 char tmp[256], t[16];
100 int i, c;
102 tmp[0]='\0';
104 if (init==-1) { // last turn said stop now!
105 init=0;
106 return 0;
109 if (init==0) {
110 cur=packet_sequences->next;
111 if (cur==NULL) {
112 str[0]='\0';
113 return 0;
115 init=1;
118 seq = (struct pseq*) cur->data;
119 if (seq==NULL) {
120 init=-1;
121 sprintf(str, "(no sequences found)");
122 return 1;
125 c = seq->count; // amount of currently stored packets in this sequence object
127 // create string with all packet IDs:
128 for (i=0; i<c; i++) {
129 pkt = seq->packet[i];
130 if (pkt == NULL) break;
131 snprintf(t, 15, "%i", pkt->id);
132 if (strnlen(tmp,256)>249) break;
133 strncat(tmp, t, 6);
134 if (i<c-1) strncat(tmp,", ", 2);
137 snprintf(str, 512, "%s {%s}", cur->name, tmp);
139 cur=cur->next;
140 if (cur==packet_sequences) init=-1; // stop next turn!
141 return 1;
145 // finds next free slot in sequence seq and adds packet mp
147 // RETURN VALUE: 0 upon success
148 // -1 failure: array full
149 // -2 failure: cannot add packets with infinite count
151 int mops_add_packet_to_sequence (struct mz_ll *seq, struct mops *mp)
153 struct pseq *cur;
154 int i;
156 if (seq==NULL) return 1;
158 // don't add packets with count=0
159 if (mp->count==0) return -2;
161 cur = (struct pseq*) seq->data;
162 if (cur->count >= MAX_PACKET_SEQUENCE_LEN) return -1; // packet array full!
163 for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
164 if (cur->packet[i]==NULL) { // found empty slot
165 cur->packet[i]=mp;
166 cur->count++;
167 return 0;
170 return 1; // never reach here
174 // adds the given delay 't' to the last packet in the sequence's pseq
176 // NOTE: return index number of pseq where delay had been added
177 // or upon failure: -1 if there is no packet yet defined
178 // -2 if array is full
179 int mops_add_delay_to_sequence (struct mz_ll *seq, struct timespec *t)
181 struct pseq *cur;
182 int i;
184 if (seq==NULL) return 1;
186 cur = (struct pseq*) seq->data;
187 i = cur->count;
188 if (i>= MAX_PACKET_SEQUENCE_LEN) return -2; // packet array full!
190 cur->gap[i-1].tv_sec = t->tv_sec;
191 cur->gap[i-1].tv_nsec = t->tv_nsec;
193 return i-1; // note: is -1 if there is no packet yet (count=0)
197 // Deletes packet and associated delay from a pseq for given index
198 // If index == -1 then the last packet/delay is removed
200 // NOTE: index range is {1..count}
202 // RETURN VALUES: 0 upon success
203 // 1 upon failure
204 // 2 upon failure, index too big
206 int mops_delete_packet_from_pseq (struct mz_ll *seq, int index)
208 struct pseq *cur;
209 int i;
211 if (seq==NULL) return 1;
212 cur = (struct pseq*) seq->data;
213 if (cur->count==0) return 1; // list is empty, nothing to delete
214 if (index>cur->count) return 2;
215 if ((index==0) || (index<-1)) return 1; // total invalid index values
216 if (index==-1) { // remove last element
217 cur->packet[cur->count-1]=NULL;
218 cur->gap[cur->count-1].tv_sec=0;
219 cur->gap[cur->count-1].tv_nsec=0;
220 } else {
221 for (i=index-1; i<(cur->count-1); i++) {
222 cur->packet[i] = cur->packet[i+1];
223 cur->gap[i].tv_sec = cur->gap[i+1].tv_sec;
224 cur->gap[i].tv_nsec=cur->gap[i+1].tv_nsec;
227 cur->count--;
228 return 0;
232 int mops_delete_all_packets_from_pseq (struct mz_ll *seq)
234 struct pseq *cur;
235 int i;
237 if (seq==NULL) return 1;
238 cur = (struct pseq*) seq->data;
239 if (cur->count==0) return 1; // list is empty, nothing to delete
240 // DELETE ALL:
241 cur->count = 0;
242 for (i=0; i<MAX_PACKET_SEQUENCE_LEN; i++) {
243 cur->packet[i] = NULL; // pointer to the packets
244 cur->gap[i].tv_sec = 0;
245 cur->gap[i].tv_nsec = 0;
247 return 0;
252 // Stops an active sequence and sets all involved packets from state SEQACT to CONFIG.
254 // RETURN VALUE: 0 upon success
255 // 1 if sequence does not exist
256 // 2 if sequence is not actice
257 int stop_sequence (char *name)
259 struct mz_ll *v;
260 struct pseq *cur;
261 int i;
263 v = mz_ll_search_name (packet_sequences, name);
264 if (v==NULL) return 1; // name not found
265 if (!v->state) return 2; // sequence is not currently active!
267 // now stop thread:
268 pthread_cancel(v->sequence_thread);
270 // reset packet states:
271 cur = (struct pseq*) v->data;
272 for (i=0; i<cur->count; i++)
273 cur->packet[i]->state=MOPS_STATE_CONFIG;
275 // reset sequence state:
276 v->state = 0;
277 return 0;
281 // runs through 'packet_sequences' and cancels all active sequences
282 // (i. e. stops threads and sets states appropriately)
284 // Comment: It might seem a bit inefficient to call 'stop_sequence' for the
285 // detailed work, but this is the more safer way and it is fast enough.
287 // RETURN VALUE: Number of stopped sequences.
289 int stop_all_sequences ()
291 struct mz_ll *cur=packet_sequences->next;
292 int i=0;
294 while (cur!=packet_sequences) {
295 if (cur!=packet_sequences) { // just for safety
296 if (stop_sequence(cur->name)==0) i++;
298 cur=cur->next;
301 return i;