2 * ATM connection wrapper
4 * $Id: connect_bus.c,v 1.1.1.1 2005/04/29 01:44:51 echo Exp $
13 #include <sys/ioctl.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <sys/types.h>
30 /* Type definitions */
32 /* Local function prototypes */
33 static void conn_init0(void);
34 static void conn_init1(void);
35 static void conn_dump(void);
36 static void conn_release(void);
37 static const char *dump_conn_type(ConnType_t type);
39 static int data_handler(const Event_t *event, void *funcdata);
40 static void conn_main(void);
42 /* Had to remove const qualifiers since not every
43 * function honored it. hessu@cs.tut.fi
45 static int join(Conn_t *conn);
46 static int idle_bad(Conn_t *conn);
48 static int data_forward(Conn_t *conn);
49 static int join_close(Conn_t *conn);
54 const Unit_t conn_unit = {
62 static Conn_t *connlist;
64 unsigned char *data_packet;
65 unsigned int data_packet_size;
67 static const char *rcsid = "$Id: connect_bus.c,v 1.1.1.1 2005/04/29 01:44:51 echo Exp $";
71 is_1 = { CE_SVC_OPEN, 0, "Idle->Oper", join, CS_OPERATIONAL },
72 is_2 = { CE_SVC_OPEN, 0, "Idle->Idle", idle_bad, CS_IDLE },
73 *idle_state[] = { &is_1, &is_2, NULL },
76 os_1 = { CE_DATA, 0, "Oper->Oper", data_forward, CS_OPERATIONAL },
77 /* os_2 = { CE_DATA, LE_FLUSH_REQUEST, "Active->Active", flush_request,
79 os_3 = { CE_SVC_CLOSE, 0, "Oper->Idle", join_close, CS_IDLE },
80 *operational_state[] = { &os_1, /*&as_2,*/ &os_3, NULL },
82 **transitions[CS_MAX + 1] = {
83 idle_state, NULL, operational_state
88 /* Initialize local data */
95 /* Initialization for data that needs other units */
99 set_var_str(&conn_unit, "version", rcsid);
101 add_event_handler(CE_DATA, &data_handler, "data_handler", NULL);
102 Debug_unit(&conn_unit, "Initialized.");
105 /* Dump status, local data etc. */
110 const AtmAddr_t *addr;
112 Debug_unit(&conn_unit, "Dumping unit");
113 Debug_unit(&conn_unit, "Parameters:");
114 addr = get_var_addr(&conn_unit, "S1");
116 Debug_unit(&conn_unit, "S1:");
120 Debug_unit(&conn_unit, "S1: not set");
122 tmp = get_var_str(&conn_unit, "S2");
124 Debug_unit(&conn_unit, "S2: %s", tmp);
127 Debug_unit(&conn_unit, "S2: not set", tmp);
129 Debug_unit(&conn_unit, "S3: %d", get_var_int(&conn_unit, "S3"));
130 Debug_unit(&conn_unit, "S4: %d", get_var_int(&conn_unit, "S4"));
131 Debug_unit(&conn_unit, "S5: %d", get_var_int(&conn_unit, "S5"));
132 addr = get_var_addr(&conn_unit, "S6");
134 Debug_unit(&conn_unit, "S6:");
138 Debug_unit(&conn_unit, "S6: not set");
143 /* Release allocated memory, close files etc. */
149 Debug_unit(&conn_unit, "Releasing unit");
151 for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
152 connlist = tmp->next;
157 mem_free(&conn_unit, tmp);
162 * Handle data arrival
163 * data points to Conn_t
166 data_handler(const Event_t *event, void *funcdata)
168 Conn_t *tmp, *newconn;
170 static char buffer[BUFSIZE];
171 struct sockaddr_atmsvc addr;
173 assert(event->data != NULL);
174 tmp = (Conn_t *)event->data;
176 if (tmp->type == CT_MAIN) {
177 nbytes = sizeof(addr);
178 memset(&addr, 0,nbytes);
179 fd = accept(tmp->fd, (struct sockaddr *)&addr, &nbytes);
181 dump_error(&conn_unit, "accept");
182 if (errno == ENETRESET) { /* Switch reseted? */
183 Debug_unit(&conn_unit,"Restart. Sleeping 10 secs...");
185 event_put(&conn_unit, CE_RESTART, NULL);
186 } else if (errno == EUNATCH) { /* Probably signalling daemon was abruptly killed */
187 Debug_unit(&conn_unit,"Exiting...");
188 event_put(&conn_unit, CE_EXIT, NULL);
192 newconn = conn_add(CT_SVC_CD, fd, 0);
193 newconn->state = call_state(CE_SVC_OPEN, 0, newconn);
196 nbytes = read(tmp->active_fd, buffer, BUFSIZE);
198 dump_error(&conn_unit, "read");
199 if (errno == EUNATCH)
200 event_put(&conn_unit, CE_EXIT, NULL);
201 if (errno == ENETRESET) {
202 Debug_unit(&conn_unit, "Restart. Sleeping 10 secs...");
204 event_put(&conn_unit, CE_RESTART, NULL);
206 } else if (nbytes == 0) {
208 Debug_unit(&conn_unit, "EOF");
209 tmp->state = call_state(CE_SVC_CLOSE, 0, tmp);
211 buffer[nbytes] = '\0';
212 data_packet = (unsigned char *)buffer;
213 data_packet_size=nbytes;
214 tmp->state = call_state(CE_DATA, 0, tmp);
217 mem_free(&conn_unit, event);
222 dump_conn_type(ConnType_t type)
225 case CT_NONE: return "None";
226 case CT_MAIN: return "Main listener";
227 case CT_PVC_CD: return "PVC Control Direct";
228 case CT_PVC_DD: return "PVC Data Direct";
229 case CT_SVC_CD: return "SVC Control Direct";
230 case CT_SVC_DD: return "SVC Data Direct";
231 default: return "Bad type";
236 dump_conn(const Conn_t *connection)
240 for(tmp = connlist; tmp != NULL; tmp = tmp->next) {
241 if (connection == NULL || tmp == connection) {
242 Debug_unit(&conn_unit, "fd %d sfd %d state %s type %s", tmp->fd, tmp->sfd, dump_conn_state(tmp->state), dump_conn_type(tmp->type));
248 conn_add(ConnType_t type, int fd, LecId_t dumb)
252 tmp = (Conn_t *)mem_alloc(&conn_unit, sizeof(Conn_t));
255 tmp->state = CS_IDLE;
257 tmp->next = connlist;
260 event_add_fd(fd, tmp);
265 conn_remove(const Conn_t *connection)
269 assert(connection != NULL);
273 if (tmp == connection) {
275 prev->next = tmp->next;
277 connlist = tmp->next;
279 if (connection->fd) {
280 close(connection->fd);
281 event_remove_fd(connection->fd);
283 if (connection->sfd) {
284 close(connection->sfd);
285 event_remove_fd(connection->sfd);
287 mem_free(&conn_unit, tmp);
296 conn_set_active(void *data, int fd)
298 Conn_t *tmp = (Conn_t *)data;
307 const AtmAddr_t *addr;
310 addr = get_var_addr(&conn_unit, "S6");
312 dump_printf(EL_ERROR, "S6 (BUS Address) must be specified");
313 event_put(&conn_unit, CE_EXIT, NULL);
315 main_conn = atm_create_socket(MULTICAST_SEND_802_3,
316 get_var_addr(&conn_unit, "S6"));
317 if (main_conn >= 0) {
318 (void)conn_add(CT_MAIN, main_conn, 0);
324 call_state(EventType_t event, unsigned short opcode, Conn_t *conn)
330 Debug_unit(&conn_unit, "Call state");
331 assert(conn != NULL);
332 assert(conn->state <= CS_MAX);
333 tmp = transitions[conn->state];
335 for(; tmp[i] != NULL; i++) {
336 if (tmp[i]->event == event && tmp[i]->opcode == opcode) {
337 Debug_unit(&conn_unit, "Trying func %s", tmp[i]->descript);
338 ret = tmp[i]->func(conn);
340 Debug_unit(&conn_unit, "Success");
341 return tmp[i]->nextstate;
344 Debug_unit(&conn_unit, "Failed");
348 Debug_unit(&conn_unit, "Skipping func %s", tmp[i]->descript);
355 dump_conn_state(ConnState_t state)
358 case CS_IDLE: return "Idle";
359 case CS_JOINING: return "Joining";
360 case CS_OPERATIONAL: return "Operational";
361 default: return "Bad state";
366 * State transition functions
373 Debug_unit(&conn_unit, "Join called");
376 rfd = atm_connect_back(get_var_addr(&conn_unit,"S6"),
377 conn, MULTICAST_FORWARD_802_3);
378 if (rfd<0) { /* Calling back failed */
381 } else { /* Success */
382 Debug_unit(&conn_unit, "Join successful");
384 event_add_fd(rfd, conn);
390 idle_bad(Conn_t *conn)
392 Debug_unit(&conn_unit,"Idle_bad called");
399 data_forward(Conn_t *conn)
402 char packet_string[1024];
406 Debug_unit(&conn_unit,"Data forward called");
409 for(tmp = connlist;tmp!=NULL;tmp=tmp->next) {
410 if (tmp->sfd >0 && tmp->type != CT_MAIN) {
411 rvalue=write(tmp->sfd, data_packet, data_packet_size);
413 dump_error(&conn_unit, "data_forward,write");
416 Debug_unit(&conn_unit,"Forwarding to %d-%d bytes",tmp->sfd,
420 Debug_unit(&conn_unit,"Sent packet :%ld bytes",data_packet_size);
421 for (i=0;i<data_packet_size && i < 83;i++) {
422 sprintf(&packet_string[3*i],"%2.2x ",0xff&data_packet[i]);
424 if (i==data_packet_size)
425 Debug_unit(&conn_unit,"Packet:->%s<-",packet_string);
427 Debug_unit(&conn_unit,"Packet:->%s->",packet_string);
428 Debug_unit(&conn_unit,"Returning from data forward");
433 join_close(Conn_t *conn)
436 Debug_unit(&conn_unit,"Join_close called");