func: static void *skinny_session(void *data) int res ; struct skinny_req * req ; struct skinnysession * s = data ; res = get_input ( s ); static int get_input(struct skinnysession *s) int res ; int timeout = keep_alive * 1100 ; time_t now ; int * bufaddr ; struct pollfd fds [ 1 ] ; if ( ! s -> device )  if ( time ( & now ) == - 1 )  return - 1 ; timeout = ( auth_timeout - ( now - s -> start ) ) * 1000; if ( timeout < 0 )  return - 1 ; fds [ 0 ] . fd = s -> fd; fds [ 0 ] . events = POLLIN; fds [ 0 ] . revents = 0; res = ast_poll ( fds , 1 , timeout ); if ( res < 0 )  if ( errno != EINTR )  return res ; if ( res == 0 )  return - 1 ; if ( fds [ 0 ] . revents )  memset ( s -> inbuf , 0 , sizeof ( s -> inbuf ) ); res = read ( s -> fd , s -> inbuf , 4 ); if ( res < 0 )  return res ; if ( res != 4 )  return - 1 ; bufaddr = ( int * ) s -> inbuf; dlen = letohl ( * bufaddr ); if ( dlen < 4 )  return - 1 ; if ( dlen + 8 > sizeof ( s -> inbuf ) )  dlen = sizeof ( s -> inbuf ) - 8; res = read ( s -> fd , s -> inbuf + 4 , dlen + 4 ); if ( res < 0 )  return res ; if ( res != ( dlen + 4 ) )  return - 1 ; return res ; return 0 ; if ( res < 0 )  if ( res > 0 )  if ( ! ( req = skinny_req_parse ( s ) ) )  static struct skinny_req *skinny_req_parse(struct skinnysession *s) struct skinny_req * req ; int * bufaddr ; if ( ! ( req = ast_calloc ( 1 , SKINNY_MAX_PACKET ) ) )  return NULL ; memcpy ( req , s -> inbuf , skinny_header_size ); bufaddr = ( int * ) ( s -> inbuf ); memcpy ( & req -> data , s -> inbuf + skinny_header_size , letohl ( * bufaddr ) - 4 ); if ( letohl ( req -> e ) < 0 )  return NULL ; return req ; res = handle_message ( req , s ); if ( res < 0 )  static int handle_message(struct skinny_req *req, struct skinnysession *s) if ( ( ! s -> device ) && ( letohl ( req -> e ) != REGISTER_MESSAGE && letohl ( req -> e ) != ALARM_MESSAGE ) )  switch ( letohl ( req -> e ) )  res = handle_button_template_req_message ( req , s ); static int handle_button_template_req_message(struct skinny_req *req, struct skinnysession *s) struct button_definition_template btn [ 42 ] ; if ( ! ( req = req_alloc ( sizeof ( struct button_template_res_message ) , BUTTON_TEMPLATE_RES_MESSAGE ) ) )  static struct skinny_req *req_alloc(size_t size, int response_message) struct skinny_req * req ; if ( ! ( req = ast_calloc ( 1 , skinny_header_size + size + 4 ) ) )  return NULL ; req -> len = htolel ( size + 4 ); req -> e = htolel ( response_message ); return req ; memset ( & btn , 0 , sizeof ( btn ) ); get_button_template ( s , btn ); static void *get_button_template(struct skinnysession *s, struct button_definition_template *btn) struct skinny_device * d = s -> device ; switch ( d -> type )  ( btn ++ ) -> buttonDefinition = BT_CUST_LINE; ( btn ++ ) -> buttonDefinition = BT_REDIAL; ( btn ++ ) -> buttonDefinition = BT_VOICEMAIL; ( btn ++ ) -> buttonDefinition = BT_CALLPARK; ( btn ++ ) -> buttonDefinition = BT_FORWARDALL; ( btn ++ ) -> buttonDefinition = BT_CONFERENCE; ( btn ++ ) -> buttonDefinition = BT_NONE; ( btn ++ ) -> buttonDefinition = BT_SPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_CUST_LINE; ( btn ++ ) -> buttonDefinition = BT_SPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_HOLD; ( btn ++ ) -> buttonDefinition = BT_REDIAL; ( btn ++ ) -> buttonDefinition = BT_TRANSFER; ( btn ++ ) -> buttonDefinition = BT_FORWARDALL; ( btn ++ ) -> buttonDefinition = BT_CALLPARK; ( btn ++ ) -> buttonDefinition = BT_VOICEMAIL; ( btn ++ ) -> buttonDefinition = BT_LINE; ( btn ++ ) -> buttonDefinition = BT_HOLD; ( btn ++ ) -> buttonDefinition = BT_TRANSFER; ( btn ++ ) -> buttonDefinition = BT_DISPLAY; ( btn ++ ) -> buttonDefinition = BT_VOICEMAIL; ( btn ++ ) -> buttonDefinition = BT_CONFERENCE; ( btn ++ ) -> buttonDefinition = BT_FORWARDALL; ( btn ++ ) -> buttonDefinition = BT_SPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_REDIAL; ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_LINE; ( btn ++ ) -> buttonDefinition = BT_LINE; ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; ast_log ( LOG_WARNING , "Unsupported device type '%d (7985)' found.\n" , d -> type ); ( btn ++ ) -> buttonDefinition = BT_LINE; ( btn ++ ) -> buttonDefinition = BT_HOLD; ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; ast_log ( LOG_WARNING , "Unsupported device type '%d (7902)' found.\n" , d -> type ); ast_log ( LOG_WARNING , "Unsupported device type '%d (7906)' found.\n" , d -> type ); ast_log ( LOG_WARNING , "Unsupported device type '%d (7931)' found.\n" , d -> type ); ast_log ( LOG_WARNING , "Unsupported device type '%d (7937)' found.\n" , d -> type ); ast_log ( LOG_WARNING , "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n" , d -> type ); ast_log ( LOG_WARNING , "Unsupported device type '%d (SCCP gateway)' found.\n" , d -> type ); ast_log ( LOG_WARNING , "Unknown device type '%d' found.\n" , d -> type ); AST_LIST_LOCK ( & d -> addons ); ( btn ++ ) -> buttonDefinition = BT_CUST_LINESPEEDDIAL; AST_LIST_UNLOCK ( & d -> addons ); return btn ; switch ( btn [ i ] . buttonDefinition )  req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_NONE; req -> data . buttontemplate . definition [ i ] . instanceNumber = 0; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_LINE; req -> data . buttontemplate . definition [ i ] . instanceNumber = lineInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_LINE; req -> data . buttontemplate . definition [ i ] . instanceNumber = lineInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_NONE; req -> data . buttontemplate . definition [ i ] . instanceNumber = 0; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_LINE; req -> data . buttontemplate . definition [ i ] . instanceNumber = lineInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_LINE; req -> data . buttontemplate . definition [ i ] . instanceNumber = lineInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_SPEEDDIAL; req -> data . buttontemplate . definition [ i ] . instanceNumber = speeddialInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = htolel ( BT_NONE ); req -> data . buttontemplate . definition [ i ] . instanceNumber = htolel ( 0 ); req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_LINE; req -> data . buttontemplate . definition [ i ] . instanceNumber = lineInstance; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_NONE; req -> data . buttontemplate . definition [ i ] . instanceNumber = 0; req -> data . buttontemplate . definition [ i ] . buttonDefinition = BT_SPEEDDIAL; req -> data . buttontemplate . definition [ i ] . instanceNumber = speeddialInstance - 1; ast_verb ( 0 , "Adding button: %d, %d\n" , btn [ i ] . buttonDefinition , 0 ); req -> data . buttontemplate . definition [ i ] . buttonDefinition = htolel ( btn [ i ] . buttonDefinition ); req -> data . buttontemplate . definition [ i ] . instanceNumber = 0; req -> data . buttontemplate . buttonOffset = 0; req -> data . buttontemplate . buttonCount = htolel ( buttonCount ); req -> data . buttontemplate . totalButtonCount = htolel ( buttonCount ); transmit_response ( d , req ); static void transmit_response(struct skinny_device *d, struct skinny_req *req) transmit_response_bysession ( d -> session , req ); static int transmit_response_bysession(struct skinnysession *s, struct skinny_req *req) if ( ! s )  ast_mutex_lock ( & s -> lock ); SKINNY_DEVONLY ( skinnydebug > 1 ast_verb ( 4 , "Transmitting %s to %s\n" , message2str ( req -> e ) , s -> device -> name ) ) static char *message2str(int type) switch ( letohl ( type ) )  snprintf ( tmp , MESSAGE2STR_BUFSIZE , "UNKNOWN_MESSAGE-%d" , type ); return tmp ; if ( ( letohl ( req -> len ) > SKINNY_MAX_PACKET ) || ( letohl ( req -> len ) < 0 ) )  ast_log ( LOG_WARNING , "transmit_response: the length of the request (%d) is out of bounds (%d)\n" , letohl ( req -> len ) , SKINNY_MAX_PACKET ); ast_mutex_unlock ( & s -> lock ); memset ( s -> outbuf , 0 , sizeof ( s -> outbuf ) ); memcpy ( s -> outbuf , req , skinny_header_size ); memcpy ( s -> outbuf + skinny_header_size , & req -> data , letohl ( req -> len ) ); res = write ( s -> fd , s -> outbuf , letohl ( req -> len ) + 8 ); if ( res != letohl ( req -> len ) + 8 )  ast_log ( LOG_WARNING , "Transmit: write only sent %d out of %d bytes: %s\n" , res , letohl ( req -> len ) + 8 , strerror ( errno ) ); if ( res == - 1 )  skinny_unregister ( NULL , s ); static int skinny_unregister(struct skinny_req *req, struct skinnysession *s) d = s -> device; if ( d )  d -> session = NULL; d -> registered = 0; AST_LIST_TRAVERSE ( & d -> speeddials , sd , list ) AST_LIST_TRAVERSE ( & d -> lines , l , list ) if ( l -> device == d )  manager_event ( EVENT_FLAG_SYSTEM , "PeerStatus" , "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n" , l -> name , d -> name ); ast_free ( req ); ast_mutex_unlock ( & s -> lock ); 