From: Paul B. S. <pa...@us...> - 2001-09-03 18:41:09
|
Update of /cvsroot/linux-atm/linux-atm/src/saal In directory usw-pr-cvs1:/tmp/cvs-serv10656/saal Added Files: Tag: V2_4_0 pdu.c pdu.h queue.c queue.h sscop.c sscop.h Makefile.am saal.c saal.h sscf.c sscf.h Log Message: --- NEW FILE: pdu.c --- /* pdu.c - SSCOP (Q.2110) PDU reader */ /* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdint.h> #include "pdu.h" #ifndef NULL #define NULL 0 #endif const char *pdu_name[] = { "???","BGN","BGAK","END","ENDAK","RS","RSAK", "BGREJ","SD","ER","POLL","STAT","USTAT","UD","MD","ERAK" }; void (*pdu_maa)(void *arg,char code,int count) = NULL; void (*pdu_diag)(int severity,const char *fmt,...) = NULL; void print_pdu(const char *label,unsigned char type,void *data, const int *length,const int *s,const int *ps,const int *r,const int *mr, const int *sq) { int len; char *list; switch (type) { case SSCOP_SD: pdu_diag(SP_DEBUG,"%s SD(S=%d,len=%d)",label,*s,*length); break; case SSCOP_POLL: pdu_diag(SP_DEBUG,"%s POLL(PS=%d,S=%d)",label,*ps,*s); break; case SSCOP_STAT: if (*length & 3) { pdu_diag(SP_WARN,"%s STAT PDU has wrong size (%d)",label, *length); break; } len = *length/4; pdu_diag(SP_DEBUG,"%s STAT(PS=%d,MR=%d,R=%d,items=%d:",label,*ps, *mr,*r,len); list = (char *) data; while (len > 1) { pdu_diag(SP_DEBUG,"%s %d..%d",label,read_netl(list), read_netl(list+4)); list += 8; len -= 2; } if (!len) pdu_diag(SP_DEBUG,"%s <last is absent>)",label); else pdu_diag(SP_DEBUG,"%s <next is> %d)",label,read_netl(list)); break; case SSCOP_USTAT: if (*length != 8) { pdu_diag(SP_WARN,"%s USTAT PDU has wrong size (%d)",label, *length); break; } list = (char *) data; pdu_diag(SP_DEBUG,"%s USTAT(MR=%d,R=%d,%d..%d)",label,*mr,*r, read_netl(list),read_netl(list+4)); break; case SSCOP_UD: pdu_diag(SP_DEBUG,"%s UD(len=%d)",label,*length); break; case SSCOP_MD: pdu_diag(SP_DEBUG,"%s MD(len=%d)",label,*length); break; case SSCOP_BGN: pdu_diag(SP_DEBUG,"%s BGN(SQ=%d,MR=%d,len=%d)",label,*sq,*mr, *length); break; case SSCOP_BGAK: pdu_diag(SP_DEBUG,"%s BGAK(MR=%d,len=%d)",label,*mr,*length); break; case SSCOP_BGREJ: pdu_diag(SP_DEBUG,"%s BGREJ(len=%d)",label,*length); break; case SSCOP_END: pdu_diag(SP_DEBUG,"%s END(S=%d,len=%d)",label,*s,*length); break; case SSCOP_ENDAK: pdu_diag(SP_DEBUG,"%s ENDAK()",label); break; case SSCOP_RS: pdu_diag(SP_DEBUG,"%s RS(SQ=%d,MR=%d,len=%d)",label,*sq,*mr, *length); break; case SSCOP_RSAK: pdu_diag(SP_DEBUG,"%s RSAK(MR=%d)",label,*mr); break; case SSCOP_ER: pdu_diag(SP_DEBUG,"%s ER(MR=%d)",label,*mr); break; case SSCOP_ERAK: pdu_diag(SP_DEBUG,"%s ERAK(MR=%d)",label,*mr); break; default: pdu_diag(SP_ERROR,"%s unknown PDU type %d\n",label,type); } } int decompose_pdu(void *maa_arg,void *msg,int size,unsigned char *type, int *length,int *s,int *ps,int *r,int *mr,int *sq) { void *last; unsigned char pad; int n; /* * *length is undefined if PDU has no variable-length data part */ if (size < 4 || (size & 3)) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN,"invalid message length (%d)", size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } last = (char *) msg+size-4; *type = SSCOP_TYPE(last); pad = SSCOP_PAD(last); n = SSCOP_N(last); *length = size-4-pad; switch (*type) { case SSCOP_SD: *s = n; break; case SSCOP_POLL: if (size != 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "POLL PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *s = n; *ps = SSCOP_N(msg); break; case SSCOP_STAT: if (size < 12) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "STAT PDU too short (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } if (*length & 3) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "STAT PDU has bad length (%d)",length); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *r = n; *mr = SSCOP_N((char *) last-4); *ps = SSCOP_N((char *) last-8); *length -= 8; break; case SSCOP_USTAT: if (size != 16) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "USTAT PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(pdu_maa,'U',0); return -1; } *r = n; *mr = SSCOP_N((char *) last-4); *length -= 4; break; case SSCOP_UD: case SSCOP_MD: break; case SSCOP_BGN: if (size < 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN,"BGN PDU too short (%d)", size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; *sq = SSCOP_SQ(last); *length -= 4; break; case SSCOP_BGAK: if (size < 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "BGAK PDU too short (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; *length -= 4; break; case SSCOP_BGREJ: if (size < 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "BGREJ PDU too short (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *length -= 4; break; case SSCOP_END: if (size < 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN,"END PDU too short (%d)", size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *s = !!SSCOP_S(last); *length -= 4; break; case SSCOP_ENDAK: if (size != 8) { pdu_diag(SP_DEBUG,"ENDAK PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); if (size < 4) return -1; /* make it work with Fore */ } break; case SSCOP_RS: if (size < 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN,"RS PDU too short (%d)", size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; *sq = SSCOP_SQ(last); *length -= 4; break; case SSCOP_RSAK: if (size != 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "RSAK PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; break; case SSCOP_ER: if (size != 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "ER PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; *sq = SSCOP_SQ(last); break; case SSCOP_ERAK: if (size != 8) { pdu_diag(pdu_maa ? SP_DEBUG : SP_WARN, "ERAK PDU has bad length (%d)",size); if (pdu_maa) pdu_maa(maa_arg,'U',0); return -1; } *mr = n; break; default: pdu_diag(SP_ERROR,"unknown PDU type %d (0x%x)",*type,*type); return -1; } return 0; } --- NEW FILE: pdu.h --- /* pdu.h - SSCOP (Q.2110) PDU reader */ /* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef PDU_H #define PDU_H #include <stdint.h> #include <atmd.h> /* SSCOP PDU types, Q.2110 section 7.1 */ #define SSCOP_BGN 1 /* Request Initialization */ #define SSCOP_BGAK 2 /* Request Acknowledgement */ #define SSCOP_BGREJ 7 /* Connection Reject */ #define SSCOP_END 3 /* Disconnect Command */ #define SSCOP_ENDAK 4 /* Disconnect Acknowledgement */ #define SSCOP_RS 5 /* Resynchronization Command */ #define SSCOP_RSAK 6 /* Resynchronization Acknowledgement */ #define SSCOP_ER 9 /* Recovery Command */ #define SSCOP_ERAK 15 /* Recovery Acknowledgement */ #define SSCOP_SD 8 /* Sequence Connection-mode Data */ #define SSCOP_POLL 10 /* Transmitter State Information with request ... */ #define SSCOP_STAT 11 /* Solicited Receiver State Information */ #define SSCOP_USTAT 12 /* Unsolicited Receiver State Information */ #define SSCOP_UD 13 /* Unnumbered User Data */ #define SSCOP_MD 14 /* Unnumbered Management Data */ /* Trailer format macros */ #define SSCOP_TRAIL(type,pad,n) (htonl((n) | ((type) << 24) | ((pad) << 30))) #define SSCOP_S_BIT 0x10000000 #define SSCOP_TYPE(last) ((read_netl(last) >> 24) & 15) #define SSCOP_PAD(last) (read_netl(last) >> 30) #define SSCOP_N(last) (read_netl(last) & 0xffffff) #define SSCOP_S(last) (read_netl(last) & SSCOP_S_BIT) #define SSCOP_SQ(last) (read_netl((char *) last-4) & 0xff) extern const char *pdu_name[]; /* Helper macros for PDU construction and decomposition */ #define PDU_VARS \ unsigned char type; \ int length; \ int s,ps,r,mr,sq #define DECOMPOSE_PDU(maa_arg,msg,size) decompose_pdu(maa_arg,msg,size,&type, \ &length,&s,&ps,&r,&mr,&sq) #define PRINT_PDU(label,data) print_pdu(label,type,data,&length,&s,&ps,&r, \ &mr,&sq) /* * Severity codes for pdu_diag. Surprisingly, they happen to have the same * numerical values as their corresponding diag counterparts. */ #define SP_DEBUG 3 #define SP_WARN 1 #define SP_ERROR 0 extern void (*pdu_maa)(void *arg,char code,int count); extern void (*pdu_diag)(int severity,const char *fmt,...); void print_pdu(const char *label,unsigned char type,void *data, const int *length,const int *s,const int *ps,const int *r,const int *mr, const int *sq); int decompose_pdu(void *maa_arg,void *msg,int size,unsigned char *type, int *length,int *s,int *ps,int *r,int *mr,int *sq); #endif --- NEW FILE: queue.c --- /* queue.c - Quick and very very dirty buffer and queue handling */ /* Written 1995-1996 by Werner Almesberger, EPFL-LRC */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <string.h> #include "atmd.h" #include "queue.h" BUFFER *buffer_create(int length,int key) { BUFFER *buf; buf = alloc_t(BUFFER); buf->data = alloc(length); buf->length = length; buf->key = key; return buf; } BUFFER *buffer_clone(BUFFER *b) { BUFFER *buf; buf = buffer_create(b->length,b->key); memcpy(buf->data,b->data,b->length); return buf; } void buffer_discard(BUFFER *b) { free(b->data); free(b); } void queue_init(QUEUE *q) { q->first = q->last = NULL; } void queue_put(QUEUE *q,BUFFER *b) { Q_INSERT_AFTER(q->first,b,q->last); q->last = b; } void queue_remove(QUEUE *q,BUFFER *b) { if (q->last == b) q->last = b->prev; Q_REMOVE(q->first,b); } BUFFER *queue_peek(QUEUE *q) { return q->first; } BUFFER *queue_get(QUEUE *q) { BUFFER *buf; buf = queue_peek(q); if (buf) queue_remove(q,buf); return buf; } BUFFER *queue_lookup(QUEUE *q,int key) { BUFFER *walk; for (walk = q->first; walk; walk = walk->next) if (walk->key == key) break; return walk; } void queue_clear(QUEUE *q) { BUFFER *next; while (q->first) { next = q->first->next; buffer_discard(q->first); q->first = next; } q->last = NULL; } --- NEW FILE: queue.h --- /* queue.h - Quick and very very dirty buffer and queue handling */ /* Written 1995-1996 by Werner Almesberger, EPFL-LRC */ #ifndef QUEUE_H #define QUEUE_H typedef struct _buffer { void *data; int length; /* TX buffer: of the entire PDU; RX buffer: of the data */ int key; /* SD.N(S) */ int extra; /* SD.N(PS) */ struct _buffer *next,*prev; } BUFFER; typedef struct { BUFFER *first,*last; } QUEUE; BUFFER *buffer_create(int length,int key); BUFFER *buffer_clone(BUFFER *b); void buffer_discard(BUFFER *b); void queue_init(QUEUE *q); void queue_put(QUEUE *q,BUFFER *b); void queue_remove(QUEUE *q,BUFFER *b); BUFFER *queue_peek(QUEUE *q); BUFFER *queue_get(QUEUE *q); BUFFER *queue_lookup(QUEUE *q,int key); void queue_clear(QUEUE *q); #endif --- NEW FILE: sscop.c --- /* sscop.c - SSCOP (Q.2110) protocol */ /* Written 1995-1999 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdint.h> #include <stdarg.h> #include <string.h> #include <netinet/in.h> /* for htonl */ #include "atmd.h" #include "sscop.h" #include "queue.h" #include "pdu.h" [...1690 lines suppressed...] { if (dsc->state != sscop_idle) diag(COMPONENT,DIAG_WARN,"stopping dsc in state %s", state_name[dsc->state]); dsc->state = sscop_idle; /* avoid send attempts */ STOP_TIMER(dsc->timer_cc); STOP_TIMER(dsc->timer_poll); STOP_TIMER(dsc->timer_noresp); STOP_TIMER(dsc->timer_keepalive); STOP_TIMER(dsc->timer_idle); queue_clear(&dsc->rx_buf); queue_clear(&dsc->tx_q); queue_clear(&dsc->tx_buf); queue_clear(&dsc->rt_q); if (dsc->last_bgn) buffer_discard(dsc->last_bgn); if (dsc->last_end) buffer_discard(dsc->last_end); if (dsc->last_rs) buffer_discard(dsc->last_rs); if (dsc->last_er) buffer_discard(dsc->last_er); if (dsc->list) free(dsc->list); } --- NEW FILE: sscop.h --- /* sscop.h - SSCOP (Q.2110) user interface */ /* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef SSCOP_H #define SSCOP_H #include <stdint.h> #include "atmd.h" #include "queue.h" typedef enum { sscop_qsaal1, /* emulate some properties of Q.SAAL1 as specified for UNI 3.0 */ sscop_q2110 /* follow Q.2110 by the letter */ } SSCOP_MODE; typedef enum { sscop_idle,sscop_outconn,sscop_inconn,sscop_outdisc, sscop_outres,sscop_inres,sscop_outrec,sscop_recresp,sscop_inrec, sscop_ready } SSCOP_STATE; typedef struct { SSCOP_STATE state; struct _sscop_user_ops *ops; void *user; /* --- Configurable parameters ----------------------------------------- */ SSCOP_MODE mode; int cf_max_cc,cf_max_pd,cf_max_stat; int cf_timer_cc,cf_timer_poll,cf_timer_noresp,cf_timer_keepalive, cf_timer_idle; /* --- SSCOP information, TX part -------------------------------------- */ int vt_s; /* send sequence number */ int vt_ps; /* poll send sequence number */ int vt_a; /* acknowledge sequence number */ int vt_pa; /* poll sequence number */ int vt_ms; /* maximum send sequence */ int vt_pd; /* SD PDUs between POLL PDUs */ int vt_cc; /* number of unacknowledged BSG, END, ER or RS PDUs */ int vt_sq; /* connection number */ /* --- SSCOP information, RX part -------------------------------------- */ int vr_r; /* receiver sequence number */ int vr_h; /* highest expected SD PDU */ int vr_mr; /* maximum acceptable (receiver) */ int vr_sq; /* connection number */ int vr_ps; /* non-Q.2110: keeps N(PS) received in last POLL for STAT */ /* Other variables */ int clear_buffers; int credit; /* Timers */ TIMER *timer_cc,*timer_poll,*timer_noresp,*timer_keepalive,*timer_idle; /* Queues and buffers */ QUEUE tx_buf,tx_q,rx_buf,rt_q; BUFFER *last_bgn,*last_end,*last_rs,*last_er; /* for retransmission */ /* Misc items */ uint32_t *list; /* STAT construction list */ } SSCOP_DSC; /* * Note: UU data of primitives carrying such is only available if * - the "user" flag is set (if available) and * - uu_data is non-NULL, and * - uu_length is non-zero * in all other cases, uu_data must not be dereferenced. * * Note: the "ind" parameter in restart indicates whether the release primitive * is an AA-RELEASE.indication (ind = 1) or to an AA-RELEASE.confirm (ind = 0). */ typedef struct _sscop_user_ops { void (*estab_ind)(void *user_data,void *uu_data,int uu_length); /* AA-ESTABLISH.indication */ void (*estab_conf)(void *user_data,void *uu_data,int uu_length); /* AA-ESTABLISH.confirm */ void (*rel_ind)(void *user_data,void *uu_data,int uu_length,int user); /* AA-RELEASE.indication */ void (*rel_conf)(void *user_data); /* AA-RELEASE.confirm */ void (*restart)(void *user_data,void *uu_data,int uu_length,int ind); /* AA-RELEASE.indication or AA-RELEASE.confirm immediately followed by AA-ESTABLISH.indication */ void (*res_ind)(void *user_data,void *uu_data,int uu_length); /* AA-RESYNC.indication */ void (*res_conf)(void *user_data); /* AA-RESYNC.confirm */ void (*rec_ind)(void *user_data); /* AA-RECOVER.indication */ void (*data_ind)(void *user_data,void *data,int length,int sn); /* AA-DATA.indication */ void (*unitdata)(void *user_data,void *data,int length); /* AA-UNITDATA.indication */ void (*retr_ind)(void *user_data,void *data,int length); /* AA-RETRIEVE.indication */ void (*retr_comp)(void *user_data); /* AA-RETRIEVE_COMPLETE.indication */ void (*maa_data)(void *user_data,void *data,int length); /* MAA-UNITDATA.indication */ int (*maa_error)(void *user_data,char code,int count); /* MAA-ERROR.indication */ void (*cpcs_send)(void *user_data,void *data,int length); } SSCOP_USER_OPS; /* Attach/detach protocol */ void start_sscop(SSCOP_DSC *dsc,SSCOP_USER_OPS *ops,void *user_data, SSCOP_MODE _mode); /* gcc 2.7.2 firmly believes "mode" can shadow ... @%! */ void stop_sscop(SSCOP_DSC *dsc); /* Connection control */ void sscop_estab_req(SSCOP_DSC *dsc,void *uu_data,int uu_length,int buf_rel); /* AA-ESTABLISH.request */ void sscop_estab_resp(SSCOP_DSC *dsc,void *uu_data,int uu_length,int buf_rel); /* AA-ESTABLISH.response */ void sscop_rel_req(SSCOP_DSC *dsc,void *uu_data,int uu_length); /* AA-RELEASE.request */ void sscop_res_req(SSCOP_DSC *dsc,void *uu_data,int uu_length); /* AA-RESYNC.request */ void sscop_res_resp(SSCOP_DSC *dsc); /* AA-RESYNC.response */ void sscop_rec_resp(SSCOP_DSC *dsc); /* AA-RECOVER.response */ /* Incoming PDU from lower layer */ void sscop_pdu(SSCOP_DSC *dsc,void *msg,int size); /* CPCS-UNITDATA.request */ /* Send data */ void sscop_send(SSCOP_DSC *dsc,void *buffer,int size); /* AA-DATA.request, 20.38 */ void sscop_unitdata(SSCOP_DSC *dsc,void *buffer,int size); /* AA-UNIDATA.request, 20.47 */ void sscop_maa_data(SSCOP_DSC *dsc,void *buffer,int size); /* MAA-UNITDATA.request, 20.47 */ /* Retrieve unsent data */ #define SSCOP_RN_UNKNOWN -2 /* -1 is (theoretically) a valid rn ... */ #define SSCOP_RN_TOTAL -3 void sscop_retrieve(SSCOP_DSC *dsc,int rn); /* AA-RETRIEVE.request */ #endif --- NEW FILE: Makefile.am --- noinst_LIBRARIES = libsaal.a libsaal_a_SOURCES = pdu.h queue.h saal.h sscf.h sscop.h pdu.c queue.c saal.c \ sscf.c sscop.c --- NEW FILE: saal.c --- /* saal.c - SAAL = SSCF+SSCOP */ /* Written 1995 by Werner Almesberger, EPFL-LRC */ #if HAVE_CONFIG_H #include <config.h> #endif #include "sscop.h" #include "saal.h" void saal_pdu(SAAL_DSC *dsc,void *buffer,int length) { sscop_pdu(&dsc->sscop,buffer,length); } --- NEW FILE: saal.h --- /* saal.h - SAAL user interface */ /* Written 1995 by Werner Almesberger, EPFL-LRC */ #ifndef SAAL_H #define SAAL_H #include "sscf.h" #include "sscop.h" #define SAAL_DSC SSCF_DSC #define SAAL_USER_OPS SSCF_USER_OPS #define start_saal start_sscf #define stop_saal stop_sscf #define saal_estab_req sscf_estab_req #define saal_rel_req sscf_rel_req #define saal_send sscf_send #define saal_unitdata sscf_unitdata void saal_pdu(SAAL_DSC *dsc,void *buffer,int length); #endif --- NEW FILE: sscf.c --- /* sscf.c - SSCF (Q.2130) protocol */ /* Written 1995,1998 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include "atmd.h" #include "sscop.h" #include "sscf.h" #define COMPONENT "SSCF" /* --- SSCOP configuration ------------------------------------------------- */ #define SSCF_MaxCC 4 /* give up after 4 retries */ #define SSCF_MaxPD 25 /* POLL after 25 SDs */ #define SSCF_Timer_CC 1000000 /* 1 sec */ #define SSCF_Timer_KEEPALIVE 2000000 /* 2 sec */ #define SSCF_Timer_NORESP 7000000 /* 7 sec */ #define SSCF_Timer_POLL 750000 /* 750 ms */ #define SSCF_Timer_IDLE 15000000 /* 15 sec */ static const char *state_name[] = { "1/2","2/2","4/10","3/4","2/5" }; /* --- Helper function(s) -------------------------------------------------- */ static void next_state(SSCF_DSC *dsc,SSCF_STATE state) { diag(COMPONENT,DIAG_DEBUG,"entering state %s",state_name[state]); dsc->state = state; } /* --- Invocation from SSCOP ----------------------------------------------- */ static void sscf_estab_ind(void *user_data,void *uu_data,int uu_length) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_11) diag(COMPONENT,DIAG_FATAL,"sscf_estab_ind in state %s", state_name[dsc->state]); next_state(dsc,sscf_410); sscop_estab_resp(&dsc->sscop,NULL,0,1); if (dsc->ops->estab_ind) dsc->ops->estab_ind(dsc->user,uu_data,uu_length); } static void sscf_estab_conf(void *user_data, void *uu_data,int uu_length) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_22) diag(COMPONENT,DIAG_FATAL,"sscf_estab_conf in state %s", state_name[dsc->state]); next_state(dsc,sscf_410); if (dsc->ops->estab_conf) dsc->ops->estab_conf(dsc->user,uu_data,uu_length); } static void sscf_restart(void *user_data,void *uu_data,int uu_length,int ind) { SSCF_DSC *dsc = user_data; if ((!ind && dsc->state != sscf_34) || (ind && (dsc->state == sscf_11 || dsc->state == sscf_34))) diag(COMPONENT,DIAG_FATAL,"sscf_restart (ind = %d) in state %s", state_name[dsc->state],ind); sscop_estab_resp(&dsc->sscop,NULL,0,1); next_state(dsc,sscf_410); if (dsc->ops->restart) dsc->ops->restart(dsc->user,uu_data,uu_length,ind); } static void sscf_rec_ind(void *user_data) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_410) diag(COMPONENT,DIAG_FATAL,"sscf_rec_ind in state %s", state_name[dsc->state]); sscop_rec_resp(&dsc->sscop); if (dsc->ops->estab_ind) dsc->ops->estab_ind(dsc->user,NULL,0); } static void sscf_rel_ind(void *user_data,void *uu_data,int uu_length,int user) { SSCF_DSC *dsc = user_data; if (dsc->state == sscf_11 || dsc->state == sscf_34) diag(COMPONENT,DIAG_FATAL,"sscf_rel_ind in state %s", state_name[dsc->state]); next_state(dsc,sscf_11); if (dsc->ops->rel_ind) dsc->ops->rel_ind(dsc->user,user ? uu_data : NULL,uu_length); } static void sscf_rel_conf(void *user_data) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_34) diag(COMPONENT,DIAG_FATAL,"sscf_rel_conf in state %s", state_name[dsc->state]); next_state(dsc,sscf_11); if (dsc->ops->rel_conf) dsc->ops->rel_conf(dsc->user); } static void sscf_data_ind(void *user_data,void *data,int length,int sn) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_410) diag(COMPONENT,DIAG_FATAL,"sscf_data_ind in state %s", state_name[dsc->state]); if (dsc->ops->data_ind) dsc->ops->data_ind(dsc->user,data,length); } static void sscf_res_ind(void *user_data,void *uu_data,int uu_length) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_410) diag(COMPONENT,DIAG_FATAL,"sscf_res_ind in state %s", state_name[dsc->state]); sscop_res_resp(&dsc->sscop); if (dsc->ops->estab_ind) dsc->ops->estab_ind(dsc->user,uu_data,uu_length); } static void sscf_res_conf(void *user_data) { SSCF_DSC *dsc = user_data; if (dsc->state != sscf_25) diag(COMPONENT,DIAG_FATAL,"sscf_res_conf in state %s", state_name[dsc->state]); next_state(dsc,sscf_410); if (dsc->ops->estab_conf) dsc->ops->estab_conf(dsc->user,NULL,0); } static void sscf_unitdata_ind(void *user_data,void *data,int length) { SSCF_DSC *dsc = user_data; if (dsc->ops->unitdata) dsc->ops->unitdata(dsc->user,data,length); } static void sscf_cpcs_send(void *user_data,void *data,int length) { SSCF_DSC *dsc = user_data; if (dsc->ops->cpcs_send) dsc->ops->cpcs_send(dsc->user,data,length); } static SSCOP_USER_OPS sscf_ops = { sscf_estab_ind, * sscf_estab_conf, * sscf_rel_ind, * sscf_rel_conf, * sscf_restart, sscf_res_ind, sscf_res_conf, sscf_rec_ind, sscf_data_ind, sscf_unitdata_ind, NULL, /* no retr_ind */ NULL, /* no retr_comp */ NULL, /* no maa_data */ NULL, /* no maa_error */ sscf_cpcs_send }; /* --- Invocation from user ------------------------------------------------ */ void start_sscf(SSCF_DSC *dsc,SSCF_USER_OPS *ops,void *user_data, SSCOP_MODE mode) { dsc->state = sscf_11; dsc->ops = ops; dsc->user = user_data; start_sscop(&dsc->sscop,&sscf_ops,dsc,mode); dsc->sscop.cf_max_cc = SSCF_MaxCC; dsc->sscop.cf_max_pd = SSCF_MaxPD; dsc->sscop.cf_timer_cc = SSCF_Timer_CC; dsc->sscop.cf_timer_poll = SSCF_Timer_POLL; dsc->sscop.cf_timer_noresp = SSCF_Timer_NORESP; dsc->sscop.cf_timer_keepalive = SSCF_Timer_KEEPALIVE; dsc->sscop.cf_timer_idle = SSCF_Timer_IDLE; } void stop_sscf(SSCF_DSC *dsc) { stop_sscop(&dsc->sscop); } void sscf_estab_req(SSCF_DSC *dsc,void *uu_data,int uu_length) { switch (dsc->state) { case sscf_11: case sscf_34: next_state(dsc,sscf_22); sscop_estab_req(&dsc->sscop,uu_data,uu_length,1); return; case sscf_410: next_state(dsc,sscf_25); sscop_res_req(&dsc->sscop,uu_data,uu_length); return; default: break; } diag(COMPONENT,DIAG_FATAL,"sscf_estab_req invoked in state %s", state_name[dsc->state]); } void sscf_rel_req(SSCF_DSC *dsc,void *uu_data,int uu_length) { switch (dsc->state) { case sscf_11: if (dsc->ops->rel_conf) dsc->ops->rel_conf(dsc->user); return; case sscf_22: case sscf_410: case sscf_25: next_state(dsc,sscf_34); sscop_rel_req(&dsc->sscop,uu_data,uu_length); return; default: break; } diag(COMPONENT,DIAG_FATAL,"sscf_rel_req invoked in state %s", state_name[dsc->state]); } void sscf_send(SSCF_DSC *dsc,void *data,int length) { switch (dsc->state) { case sscf_11: return; case sscf_410: sscop_send(&dsc->sscop,data,length); return; default: break; } diag(COMPONENT,DIAG_WARN,"sscf_send invoked in state %s", state_name[dsc->state]); /* make fatal later @@@ */ } void sscf_unitdata(SSCF_DSC *dsc,void *data,int length) { sscop_unitdata(&dsc->sscop,data,length); } --- NEW FILE: sscf.h --- /* sscf.h - SSCF (Q.2130) user interface */ /* Written 1995,1998 by Werner Almesberger, EPFL-LRC/ICA */ #ifndef SSCF_H #define SSCF_H #include "sscop.h" typedef enum { sscf_11,sscf_22,sscf_410,sscf_34,sscf_25 } SSCF_STATE; typedef struct { SSCF_STATE state; struct _sscf_user_ops *ops; void *user; SSCOP_DSC sscop; } SSCF_DSC; typedef struct _sscf_user_ops { void (*estab_ind)(void *user_data,void *uu_data,int uu_length); /* AAL-ESTABLISH.indication */ void (*estab_conf)(void *user_data,void *uu_data,int uu_length); /* AAL-ESTABLISH.confirm */ void (*rel_ind)(void *user_data,void *uu_data,int uu_length); /* AAL-RELEASE.indication */ void (*rel_conf)(void *user_data); /* AAL-RELEASE.confirm */ void (*restart)(void *user_data,void *uu_data,int uu_length,int ind); /* AAL-RELEASE.indication or AAL-RELEASE.confirm immediately followed by AAL-ESTABLISH.indication */ void (*data_ind)(void *user_data,void *data,int length); /* AAL-DATA.indication */ void (*unitdata)(void *user_data,void *data,int length); /* AAL-UNITDATA.indication */ void (*cpcs_send)(void *user_data,void *data,int length); } SSCF_USER_OPS; /* Attach/detach protocol */ void start_sscf(SSCF_DSC *dsc,SSCF_USER_OPS *ops,void *user_data, SSCOP_MODE _mode); /* gcc 2.7.2 firmly believes "mode" can shadow ... @%! */ void stop_sscf(SSCF_DSC *dsc); /* Connection control */ void sscf_estab_req(SSCF_DSC *dsc,void *uu_data,int uu_length); void sscf_rel_req(SSCF_DSC *dsc,void *uu_data,int uu_length); /* Send data */ void sscf_send(SSCF_DSC *dsc,void *data,int length); void sscf_unitdata(SSCF_DSC *dsc,void *data,int length); #endif |