diff --git a/apps/tests/TestRPL/udp/Makefile b/apps/tests/TestRPL/udp/Makefile index a9c2dba7a1..ca7d1388a5 100644 --- a/apps/tests/TestRPL/udp/Makefile +++ b/apps/tests/TestRPL/udp/Makefile @@ -80,14 +80,14 @@ CFLAGS+=-DPACKET_INTERVAL=5120UL CFLAGS+=-DRPL_ROOT_ADDR=11 -<<<<<<< HEAD -# enable printf -CFLAGS += -DNEW_PRINTF_SEMANTICS -DPRINTFUART_ENABLED -DPRINTF_BUFFER_SIZE=1024 -======= + + + + GOALS += blip rpl ->>>>>>> BLIP+RPL: updating /apps + TINYOS_ROOT_DIR?=../../../.. include $(TINYOS_ROOT_DIR)/Makefile.include diff --git a/apps/tests/blip/TestLinkLocal/Makefile b/apps/tests/blip/TestLinkLocal/Makefile index 9d8daec918..4cd7bcfb0b 100644 --- a/apps/tests/blip/TestLinkLocal/Makefile +++ b/apps/tests/blip/TestLinkLocal/Makefile @@ -1,5 +1,7 @@ COMPONENT=TestLinkLocalAppC +GOALS += blip TINYOS_ROOT_DIR?=../../../.. include $(TINYOS_ROOT_DIR)/Makefile.include CFLAGS += -DIN6_NO_GLOBAL -DLIB6LOWPAN_HC_VERSION=-1 CFLAGS += -DPRINTFUART_ENABLED +PFLAGS += -DIN6_PREFIX=\"fec0::\" diff --git a/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc b/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc index 1690b2c06c..9727ec3d77 100644 --- a/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc +++ b/apps/tests/blip/TestLinkLocal/TestLinkLocalAppC.nc @@ -15,6 +15,7 @@ configuration TestLinkLocalAppC { TestLinkLocalC.Timer -> TimerMilliC; TestLinkLocalC.Leds -> LedsC; + components PrintfC,SerialStartC; components StaticIPAddressTosIdC; // Use TOS_NODE_ID in address //components StaticIPAddressC; // Use LocalIeee154 in address } diff --git a/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc b/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc index 29c484d45e..0dcdf41438 100644 --- a/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc +++ b/apps/tests/blip/TestLinkLocal/TestLinkLocalC.nc @@ -1,5 +1,5 @@ -#include +#include "blip_printf.h" #include module TestLinkLocalC { @@ -23,7 +23,6 @@ module TestLinkLocalC { }; event void Boot.booted() { - printfUART_init(); call SplitControl.start(); m_data.seqno = 0; } @@ -51,16 +50,16 @@ module TestLinkLocalC { event void Sock.recvfrom(struct sockaddr_in6 *src, void *payload, uint16_t len, struct ip6_metadata *meta) { nx_struct echo_state *cmd = payload; - printfUART("TestLinkLocalC: recv from: "); - printfUART_in6addr(&src->sin6_addr); - printfUART("\n"); + printf("TestLinkLocalC: recv from: "); + printf_in6addr(&src->sin6_addr); + printf("\n"); if (cmd->cmd == CMD_ECHO) { cmd->cmd = CMD_REPLY; call Sock.sendto(src, payload, len); call Leds.led1Toggle(); } else { - printfUART("TestLinkLocalC: reply seqno: %li\n", cmd->seqno); + printf("TestLinkLocalC: reply seqno: %li\n", cmd->seqno); call Leds.led2Toggle(); } } diff --git a/tos/lib/net/sslp/DA/SSLC_DA.nc b/tos/lib/net/sslp/DA/SSLC_DA.nc new file mode 100755 index 0000000000..a34e1a88f4 --- /dev/null +++ b/tos/lib/net/sslp/DA/SSLC_DA.nc @@ -0,0 +1,50 @@ + + +configuration SSLC_DA +{ + + provides interface SplitControl; + + +} + +implementation +{ + components SSLP_DA; + SplitControl = SSLP_DA; + + components IPStackC; + SSLP_DA.RadioControl->IPStackC; + + components new TimerMilliC() as DATimer; + SSLP_DA.DATimer -> DATimer; + + components new TimerMilliC() as DeleteTimer; + SSLP_DA.DeleteTimer -> DeleteTimer; + + components new UdpSocketC() as Send, + new UdpSocketC() as Receive; + + SSLP_DA.UDPSend -> Send; + SSLP_DA.UDPReceive -> Receive; + + components IPAddressC; + SSLP_DA.IPAddress->IPAddressC; + + components LedsC; + SSLP_DA.Leds -> LedsC; + + // #ifdef RPL_ROUTING + // components RPLRoutingC; + //#endif + + +#ifdef IN6_PREFIX + components StaticIPAddressTosIdC; +#endif + + + + + +} diff --git a/tos/lib/net/sslp/DA/SSLP_DA.nc b/tos/lib/net/sslp/DA/SSLP_DA.nc new file mode 100755 index 0000000000..39624123bd --- /dev/null +++ b/tos/lib/net/sslp/DA/SSLP_DA.nc @@ -0,0 +1,604 @@ +#include "sslp.h" +#define DA_SCOPE "embd" +module SSLP_DA +{ + provides interface SplitControl; + uses interface SplitControl as RadioControl; + uses interface Timer as DeleteTimer; + uses interface Timer as DATimer; //this can be macroed + uses interface UDP as UDPSend; + uses interface UDP as UDPReceive; + uses interface IPAddress; + uses interface Leds; + + + + +} + +implementation +{ + + uint32_t pkt_count=0; + uint8_t running=FALSE; //Indicates Whether the SSLP is On or OFF.ON=TRUE,OFF=FALSE + reg_services registered_services[STORE_MAX_SERVICES]; //DA store all the registered services in this buffer + struct in6_addr SRVLOC_DA; //This is the address for receiving UA and SA has to join for receiving DA-ADVT messages + struct in6_addr SRVLOC; //this is the address for receiving Service Type Request and Attribute Type Request messages + service_reply_msg srep_msg; //Service Reply Message + servicetype_reply_msg strep_msg; //Service Type Reply Message + directory_advt_msg dadv_msg; //Directory Advertisement Message + service_ack_msg sack_msg; //Service Acknowledgment Message + + + uint32_t DA_PERIOD=CONFIG_DA_BEAT; + + struct sockaddr_in6 dest; //Structure used for filling the UDP address(IP+Port) + char buff[64]; + + + + //Initialize all the IPAddresses here + void init() + { + inet_pton6("ff02::116",&SRVLOC_DA); + inet_pton6("ff02::123",&SRVLOC); + call DeleteTimer.startPeriodic(60000U); //Timer every one minute + } + + /*This function returns the length of the string*/ + uint8_t stringlength(char *data) + { + uint8_t i; + uint8_t count=0; + for(i=0;*(data+i)!='\0';i++) + count++; + return count; + } + + + //This function converts ip address to string + char * IPtoString(struct in6_addr *ip) + { + inet_ntop6(ip,buff,64); + return buff; + } + + //This function is used to fill the header of the SSLP Messages + void fillHeader(struct sslp_hdr *header,uint8_t type,uint16_t seq_no) + { + header->version=SSLP_VERSION; + header->msgid=type; + if(type==SERVICE_REGISTRATION) //Section 4 of the draft + header->F_flag=1; + header->seq_no=seq_no; + //printf("\n the sequence number sent is %d",seq_no); + } + + //Used only in DA so can be macroed + void getDirectoryURL(char *DirectoryURL) + { + struct in6_addr LLAddress; + call IPAddress.getLLAddr(&LLAddress); + //memcpy(&DirectoryURL[stringlength(DirectoryURL)],"service:directory-agent://",stringlength("service:directory-agent://")); + memcpy(&DirectoryURL[stringlength(DirectoryURL)],IPtoString(&LLAddress),stringlength(IPtoString(&LLAddress))); + + DirectoryURL[stringlength(DirectoryURL)]='\0'; + + + } + + //Returns 0 when it is duplicate else returns 1 when it is not duplicate or when no entry exists + int duplicate(char *service,char *scope,char *url) + { + uint8_t i; + + for(i=0;ilocation_entry.lifetime) + return ILLEGAL_REGISTRATION; + + if(sreg->sslp_header.F_flag) //Fresh Registration + { + //printf("\n Fresh Registration"); + for(index=0;indexservice_type,sreg->scope,sreg->location_entry.url)) + { + memcpy(®istered_services[index].servicetype,sreg->service_type,sreg->length_service_type+1); + registered_services[index].servicetype[stringlength(registered_services[index].servicetype)]='\0'; + memcpy(®istered_services[index].url,sreg->location_entry.url,sreg->location_entry.length_url); + memcpy(®istered_services[index].scope,sreg->scope,sreg->length_scope_type); + registered_services[index].lifetime=sreg->location_entry.lifetime; + printf("%s registered with length:%d\n",sreg->service_type, + sreg->length_service_type); + printfflush(); + return 0; + } + else{ + + return ILLEGAL_REGISTRATION; + } + } + else{ + + return ILLEGAL_REGISTRATION; + } + + } + else{ //update the registration lifetime here + int i = findService(sreg->service_type); + if(i==-1) //If it is a renewal registration but no service is present in the cache + { + + return ILLEGAL_REGISTRATION; + + } + registered_services[i].lifetime= sreg->location_entry.lifetime; + //printf("\n Renewal in the registration"); + + return 0; + + } + + } + + int DeRegisterService(servicederegistration *sdereg) + { + //first find the index + uint8_t index; + for(index=0;indexservice_type,®istered_services[index].servicetype,sdereg->length_service_type))&& + !(memcmp(sdereg->scope,®istered_services[index].scope,sdereg->length_scope_type))) + { + memset(®istered_services[index],0,sizeof(registered_services[index])); + break; + } + + + } + if(index==STORE_MAX_SERVICES) + return ILLEGAL_REGISTRATION; + + return 0; + } + + void printRegisteredServices() + { + uint8_t index; + printf("\nservices present"); + for(index=0;index>4)&0x0f) | //Adding the version + (((*buffer)>>10)&0x30) | //getting the two bits of msgid + (((*buffer)<<6)&0x3c0) | //getting the four bits of msgid + (((*buffer)>>2)&0xc00) | //getting the flags + (((*buffer)<<4)&0xf000) | //getting the reserved + (((*buffer)<<8)&0xff000000) | //getting the 8 bits of the seq + (((*buffer)>>8)&0x00ff0000) ; //getting the next 8 bits of the sequence number + + hdr=(struct sslp_hdr *)buffer; + return hdr; + } + +/***********************************************Send Handlers******************************************************************/ + + //Handler to send the Service Acknowledgement Message + + void srvack_send(struct sockaddr_in6 *destination,uint16_t seq_no,uint8_t error_code) + { + memset(&sack_msg,0,sizeof(sack_msg)); + + //Filling the Service Acknowledgment Message Header + + fillHeader(&sack_msg.sslp_header,SERVICE_ACKNOWLEDGE,seq_no); + + //Filling the Message Details + sack_msg.error_code=error_code; + + call UDPSend.sendto(destination,&sack_msg,sizeof(sack_msg)); + //printf("\n sending the service acknowledgement message"); + + } + + //Handler to send the Directory Advertisement Message + //This is used only by the Directory Agent and it can be macroed + //Parameter: the destination address either the multicast address or unicast address + void directoryadv_send(struct in6_addr *destination) + { + memset(&dadv_msg,0,sizeof(dadv_msg)); + //Filling the Directory Advertisement Message Header + fillHeader(&dadv_msg.sslp_header,DA_ADVERTISEMENT,1234); //TODO:macro the sequence number + + //Filling the Message Details + + dadv_msg.error_code= NO_ERROR; + + dadv_msg.location_entry.lifetime=600; + dadv_msg.location_entry.LT =URL_ADDR; + getDirectoryURL(dadv_msg.location_entry.url); + dadv_msg.location_entry.length_url=stringlength(dadv_msg.location_entry.url); + memcpy(dadv_msg.scope,DA_SCOPE,stringlength(DA_SCOPE)); + //printf("\n scope is %s",dadv_msg.scope); + dadv_msg.length_scope_list = stringlength(dadv_msg.scope); + printf("\nDirectory URL is %s",dadv_msg.location_entry.url); + printf("\n Directory URL Length :%d",dadv_msg.location_entry.length_url); + printfflush(); + + //Filling the UDP Header + dest.sin6_port=htons(SSLP_LISTENING_PORT); + memcpy(&dest.sin6_addr,destination,sizeof(struct in6_addr)); + //Sending the Message + call UDPSend.sendto(&dest,&dadv_msg,sizeof(dadv_msg)); + //printf("\n sending the Directory Advertisement Message"); + //printfflush(); + } + + + //Handler to send the Service Type Reply Message + + void srvtyperep_send(servicetype_request_msg *msg,uint16_t error_code,struct sockaddr_in6 *destination) + { + + memset(&strep_msg,0,sizeof(strep_msg)); + //Filling the Service Type Reply Message Header + fillHeader(&strep_msg.sslp_header,SERVICE_TYPE_REPLY,msg->sslp_header.seq_no); + + //Filling the Message Details + //printf("\n the scope received is %s",msg->scope); + strep_msg.error_code=error_code; + fillAllServices(strep_msg.servicetype,msg->scope); + strep_msg.length_servicetype=stringlength(strep_msg.servicetype); + printf("\n length of the services sent is %d",strep_msg.length_servicetype);printfflush(); + //Sending the Message + destination->sin6_port=htons(SSLP_LISTENING_PORT); + call UDPSend.sendto(destination,&strep_msg,sizeof(strep_msg)); + //printf("\n sending service type reply message sent to with length:%d ",sizeof(strep_msg)); + //printf_in6addr(&destination->sin6_addr); + //printf("port is %u",ntohs(destination->sin6_port)); + //printfflush(); + } + +/*****************************************Receive Handlers**********************************************************************/ + + //Receive Handler for the service Request Message + void srvrqst_rcv(struct sockaddr_in6 *from, void *data) + { + service_request_msg *servicemsg=(service_request_msg *)data; + uint8_t index; + + //check whether the service request is directory-agent + + if(!memcmp(&servicemsg->service_type,"service:directory-agent",stringlength("service:directory-agent"))) + { + //printf("\n iam da and i have to send a unicast service request"); + directoryadv_send(&from->sin6_addr); + } + else + { + + printRegisteredServices(); + if(findService(servicemsg->service_type)!=-1) + { + //printf("\nservice :%s is present with scope length:%d",servicemsg->service_type, + //servicemsg->length_scope_list); + //Send a Service reply with those service type + memset(&srep_msg,0,sizeof(srep_msg)); + //Filling the service reply message header + fillHeader(&srep_msg.sslp_header,SERVICE_REPLY,servicemsg->sslp_header.seq_no); + index=findService(servicemsg->service_type); + if((memcmp(servicemsg->scope,®istered_services[index].scope, + stringlength(registered_services[index].scope))) && + ((memcmp(servicemsg->scope,"default",stringlength("default"))) && + (servicemsg->length_scope_list))) + { + //Filling the Message Details + srep_msg.error_code=SCOPE_ERROR; + //printf("\nSCOPE ERROR"); + } + else + { + //printf("\nNO Error"); + srep_msg.error_code = NO_ERROR; + srep_msg.location_entry_count=1; + srep_msg.location_entry.lifetime= registered_services[index].lifetime; + srep_msg.location_entry.LT=URL_ADDR; + memcpy(&srep_msg.location_entry.url,®istered_services[index].url, + stringlength(registered_services[index].url)); + srep_msg.location_entry.length_url=stringlength(registered_services[index].url); + } + + } + else //service is not found and will send a service reply with zero service location entries + { + memset(&srep_msg,0,sizeof(srep_msg)); + //Filling the Service Reply Message Header + fillHeader(&srep_msg.sslp_header,SERVICE_REPLY,servicemsg->sslp_header.seq_no); + + //Filling the Message details + + srep_msg.error_code=NO_ERROR; + srep_msg.location_entry_count=0; //TODO:Make dynamic + //printf("\n sending service reply message with zero location entries"); + + } + from->sin6_port=htons(SSLP_LISTENING_PORT); + call UDPSend.sendto(from,&srep_msg,sizeof(service_reply_msg)); + //printf("\n service url sent is %s",registered_services[index].url); + //printfflush(); + + //printfflush(); + } + + } + + + //Receive Handler for the Service Type Request Message + void srvtyperqst_rcv(struct sockaddr_in6 *from,void *data) + { + //sending a service type reply message + printf("service type request received from"); + printf_in6addr(&from->sin6_addr); + printfflush(); + srvtyperep_send((servicetype_request_msg *)data,NO_ERROR,from); + + } + + + +/***************************************SplitControl Implementation***********************************************************/ + + command error_t SplitControl.start() + { + running=TRUE; + init(); + call UDPSend.bind(SSLP_TRANSMIT_PORT); + call UDPReceive.bind(SSLP_LISTENING_PORT); + + + + //call RadioControl.start(); + + //printf("\n starting the DA Timer"); + //printfflush(); + //TODO:Uncomment the following two lines after ND Works:Jamal + directoryadv_send(&SRVLOC_DA); + call DATimer.startPeriodic(DA_PERIOD); + + return SUCCESS; + + + } + + command error_t SplitControl.stop() + { + + + + } + + + + +/********************************************EVENTS****************************************************************************/ + + event void UDPSend.recvfrom(struct sockaddr_in6 *from, void *data, + uint16_t len, struct ip6_metadata *meta) { + + } + + + event void UDPReceive.recvfrom(struct sockaddr_in6 *from, void *data, + uint16_t len, struct ip6_metadata *meta) { + + + struct sslp_hdr *header; + if(call IPAddress.isLLAddress(&from->sin6_addr)) + { + //printf("\n local address"); + //printfflush(); + header=(struct sslp_hdr *)data; + } + else{ + //printf("\n globaladdress"); + //printf_in6addr(&from->sin6_addr); + header=getHeader(data); + //printfflush(); + }header=getHeader(data); + //printf("\n sequence number received is %u",header->seq_no); + //printf("\n version is %d",header->version); + printf("\n message id is %d",header->msgid);printfflush(); + //printf("\n o flag is %d",header->O_flag); + //printf("\n f flag is %d",header->F_flag); + //printf("\n reserved is %d",header->rsv); + //printfflush(); + call Leds.led0Toggle(); + //printf("\n checking the type of the message received"); + if(header->msgid==SERVICE_REQUEST) + { + + printf("\n Service Request Message is received"); + srvrqst_rcv(from,data); + } + else if(header->msgid==SERVICE_REGISTRATION) + { + serviceregistration *sreg=(serviceregistration *)data; + //Send the service acknowledgement and add it in his buffer + printf("\n service registration message is received"); + printfflush(); + srvack_send(from,header->seq_no,RegisterService(sreg)); + } + else if(header->msgid==SERVICE_DEREGISTRATION) + { + servicederegistration *sdereg = (servicederegistration *)data; + //Deregister the service + //send the service acknowledgement + //printf("\n service deregistration message is received"); + srvack_send(from,header->seq_no,DeRegisterService(sdereg)); + } + else if(header->msgid==SERVICE_TYPE_REQUEST) + { + + servicetype_request_msg *msg=(servicetype_request_msg *)data; + call Leds.led1Toggle(); + printf("\n Service Type Request Message is Received"); + printf("\n scope received is %s",msg->scope); + printfflush(); + srvtyperqst_rcv(from,data); + }else if(header->msgid==DA_ADVERTISEMENT){ + call Leds.led2Toggle(); + printf("Directory Advertisement Message is received"); + printfflush(); + } + else{ + // call Leds.led0Toggle(); + + //printf("\n some other message is received with message id :%d",header->msgid); + //printfflush(); + } + + + } + + event void RadioControl.startDone(error_t e) { + + + } + + + event void RadioControl.stopDone(error_t e) { + signal SplitControl.stopDone(SUCCESS); + } + + + //macro this thing + event void DATimer.fired() + { + directoryadv_send(&SRVLOC_DA); + + } + + event void DeleteTimer.fired() + { + uint8_t i; + for(i=0;i +@version $Revision: 1.0 + +*/ + +#ifndef SSLP_H +#define SSLP_H + +#include + +struct sslp_hdr{ + uint8_t version:4; //contains the version of the sslp being used + uint8_t msgid:6; //determines the message type + uint8_t O_flag:1; //O(Overflow) flag is set when the message length exceeds what can fit into the datagram + uint8_t F_flag:1; //F(Fresh) flag is set on every SREG + uint8_t rsv:4; //reserved + uint16_t seq_no; //set to a unique value for each unique SREQ message.If the request message is retransmitted,the same sequence number is used.Replies set the sequence number to the same value as the sequence number in the SREQ message. +}__attribute__((packed)); + + +//service request message +/*Service Request Messages are sent by UA to SA to get the location of service specified in the service type*/ +typedef struct service_request_msg{ + struct sslp_hdr sslp_header; //header with message-id=1 + uint8_t AM:2; //addressing mode specifies the size of the source address + uint8_t reserved:6; + //uint8_t reserved1; + struct in6_addr ip_address; //we are fixing the AM mode to IP Address here + uint16_t length_service_type; + char service_type[24]; //services should be defined according to the service template + uint16_t length_scope_list; + char scope[16]; +}__attribute__((packed))service_request_msg; + + +//sslp -draft + + + +typedef struct servicelocation_entry{ + uint16_t lifetime; + uint8_t LT:2; + uint8_t reserved:6; + uint16_t length_url; + char url[80]; //TODO:CHANGE at pc to 24 from 48 //make sure while sending from pc u have to append "*" so that overwritten of data does not takes place..A service of a particular type announces its availability with a service:url that includes a domain name or ip address,and possibly its port number and optionally basic configuration parameters +}__attribute__((packed))servicelocation_entry; + +//service Reply Message + +typedef struct service_reply_msg{ + struct sslp_hdr sslp_header; //header with message-id=2 + uint16_t error_code; + uint16_t location_entry_count; + servicelocation_entry location_entry; +}__attribute__((packed))service_reply_msg; + +//Service Registration Message + +typedef struct serviceregistration{ + struct sslp_hdr sslp_header; + + servicelocation_entry location_entry; + + uint16_t length_service_type; + char service_type[24]; + uint16_t length_scope_type; + char scope[16]; +}__attribute__((packed))serviceregistration; + + +//Service Deregistration Message +//Used for deregistering a service present +typedef struct servicederegistration { + struct sslp_hdr sslp_header; //header with message id is 9 + + servicelocation_entry location_entry; + uint16_t length_service_type; + char service_type[24]; + uint16_t length_scope_type; + char scope[12]; +}__attribute__((packed))servicederegistration; + + + +//service type request message is used by UA to get all the services present in the network +typedef struct servicetype_request_msg{ + struct sslp_hdr sslp_header; //header with message id=7 + uint8_t AM:2; + uint8_t reserved:6; + //uint8_t reserved1; //for padding + struct in6_addr ip_address; //we are fixing the AM mode to IP Address here + uint16_t length_scope_list; + char scope[16]; +}__attribute__((packed))servicetype_request_msg; + + +//service Type Reply Message +//message send in response to Service Type Request + +typedef struct servicetype_reply_msg { + struct sslp_hdr sslp_header; + uint16_t error_code; + uint16_t length_servicetype; + char servicetype[60]; +}__attribute__((packed))servicetype_reply_msg; + + +//Directory Advertisement Message +//Message sent by DA in response to a Service Request Message with service type:service:directory-agent or periodically it sends a unsolicited message to inform that he is present in the network + +typedef struct Directory_Advt_msg { + struct sslp_hdr sslp_header; + uint16_t error_code; //error_code should be sent to zero when DA broadcasts + servicelocation_entry location_entry; //url should contain service:directory-agent://" of the DA" + uint16_t length_scope_list; + char scope[8]; //the scope list of the DA must not be null +}__attribute__((packed))directory_advt_msg; + + + + +//Service Acknowledgement Messages + +typedef struct service_ack_msg{ + struct sslp_hdr sslp_header; + uint16_t error_code; +}__attribute__((packed))service_ack_msg; + + + +//Service Acknowledgement Messages(SACK) are received in response to the SREG messages +typedef struct { + char service[16]; + char url[100]; + char scope[16]; + uint16_t lifetime; +}__attribute__((packed))services_available; + +//Storing the registered services in the datastructure + +typedef struct reg_services{ + char servicetype[24]; + uint16_t lifetime; + char url[100]; + char scope[16]; +}__attribute__((packed))reg_services; + + +typedef struct { + char service[16]; + char scope[16]; + uint8_t sequence_no; +}__attribute__((packed))sequencer; + +enum{ + + NO, + YES, +}; + +enum { +RETRANSMIT +}; + +//error types + +enum{ + NO_ERROR=0, + PARSING_ERROR=1, + SCOPE_ERROR=2, + INTERNAL_ERROR=3, + MSG_NOT_SUPPORTED=4, + ILLEGAL_REGISTRATION=5, + DA_BUSY=6, +}; +//Addressing Mode Types + +enum{ + + SHORT_ADDR=1, + EXTENDED_ADDR=2, + IP_ADDR=3, + URL_ADDR=3, +}; + +//Return Types + +enum{ + SERV_SCOPE=1, //Both service and Scope Matches + SERV=2, //Only Service Matches + NONE=3, //None Matches +}; +//Message Types + + +enum{ + SERVICE_REQUEST=1, + SERVICE_REPLY=2, + SERVICE_REGISTRATION=3, + SERVICE_ACKNOWLEDGE=4, + DA_ADVERTISEMENT=5, + SA_ADVERTISEMENT=6, + SERVICE_TYPE_REQUEST=7, + SERVICE_TYPE_REPLY=8, + SERVICE_DEREGISTRATION=9, +}; + +#define SSLP_VERSION 2 +/*(Section 5.3 of RFC2608)Request which fails to give a response are retransmitted. The initial retransmissions occurs after a CONFIG_RETRY wait period.Retransmissions must be made with exponentially increasing wait intervals(doubling the wait each time) +Multicast requests should be reissued over CONFIG_MC_MAX seconds untill a result has been obtained +*/ + + +#define CONFIG_DA_BEAT 10800000U //3 Hours +//CONFIG_DA_BEAT is the interval after which DA sends unsolicited Directory Advertisements Messages so that SA and UA can recognize that there is a DA in the network +#define CONFIG_RETRY 2000U //2 Seconds +#define CONFIG_MC_MAX 15000U //15 Seconds + +#define STORE_MAX_SERVICES 5 //Maximum amount of services we can store +#define STORE_MAX_SEQUENCES 5 //Maximum amount of sequencese we can store +#define WAIT_PERIOD_SREPLY 10000U //Maximum amount of time we will wait for service reply if messages received after this will be discarded +#define PRINTTIMER_PERIOD 5000U //delay between each print +#define MAX_SERVICE_ADVERTISE 2 //Maximum services the SA can advertise + +#define SSLP_LISTENING_PORT 4270 //According to RFC 2608(Section 6.1) +#define SSLP_TRANSMIT_PORT 441 //This can be anything +#define MAX_DA_ADDR 3 //Maximum number of DA Addresses that can be stored +#define CONFIG_REG_ACTIVE 3000 //Wait to register services on passive DA discovery + +#endif diff --git a/tos/lib/net/sslp/SA_UA/SSLC.nc b/tos/lib/net/sslp/SA_UA/SSLC.nc new file mode 100755 index 0000000000..4130a8ec08 --- /dev/null +++ b/tos/lib/net/sslp/SA_UA/SSLC.nc @@ -0,0 +1,59 @@ + + +configuration SSLC +{ + + provides interface SplitControl; + provides interface ServiceLocation; + +} + + +implementation +{ + components SSLP; + SplitControl=SSLP; + ServiceLocation=SSLP; + + + components IPStackC; + SSLP.RadioControl->IPStackC; + + + components new UdpSocketC() as Send, + new UdpSocketC() as Receive; + + SSLP.UDPSend -> Send; + SSLP.UDPReceive -> Receive; + + + components new TimerMilliC() as PrintTimer; + SSLP.PrintTimer->PrintTimer; + + + components new TimerMilliC() as RetransmitTimer; + SSLP.RetransmitTimer->RetransmitTimer; + + #ifdef NODE_UA + components new TimerMilliC() as StorageTimer; + SSLP.StorageTimer -> StorageTimer; + #endif + + components new TimerMilliC() as DelayTimer; + SSLP.DelayTimer -> DelayTimer; + + + components SSLPNodeC; + SSLP.SSLPNode->SSLPNodeC; + + + components IPAddressC; + SSLP.IPAddress->IPAddressC; + + + components LedsC; + SSLP.Leds -> LedsC; + + components RandomC; + SSLP.Random -> RandomC; +} diff --git a/tos/lib/net/sslp/SA_UA/SSLP.nc b/tos/lib/net/sslp/SA_UA/SSLP.nc new file mode 100755 index 0000000000..1255a20b23 --- /dev/null +++ b/tos/lib/net/sslp/SA_UA/SSLP.nc @@ -0,0 +1,968 @@ +#include "sslp.h" +#include +module SSLP +{ + provides interface SplitControl; + provides interface ServiceLocation; + + + uses interface SplitControl as RadioControl; + uses interface UDP as UDPSend; + uses interface UDP as UDPReceive; + uses interface Timer as RetransmitTimer; + uses interface Timer as PrintTimer; + #ifdef NODE_UA + uses interface Timer as StorageTimer; + #endif + uses interface Timer as DelayTimer; + uses interface SSLPNode; + uses interface IPAddress; + uses interface Leds; + uses interface Random; + +} + + +implementation +{ + bool DA_AVAILABLE=FALSE; //This variable will tell whether we can check whether DA is present or not + + uint8_t running=FALSE; //Indicates Whether the SSLP is On or OFF.ON=TRUE,OFF=FALSE + #ifdef NODE_UA + services_available services[STORE_MAX_SERVICES]; //UA store the services information in this buffer + servicelocation_entry entries[STORE_MAX_SERVICES]; //Storing the received location entries in this + uint8_t location_entriescount=0; + char services_received[64]; //store all the service types in this message + #endif + struct in6_addr DA_IP; + char global_service[16],global_scope[16]; //these variables are mainly to be used at the retransmission.If u suppose send the message and u did not receive the message then we will use these variables + uint8_t global_service_len,global_scope_len; + sequencer available_sequences[STORE_MAX_SEQUENCES]; //This structure stores the scope and service for a particular sequence + + + + + uint8_t indexer=0; //This is used in sequencer logic to overwrite if the array is full + + char append[28]; //This is Mainly For appending the Service to the service String + + struct sockaddr_in6 dest; //Structure used for filling the UDP address(IP+Port) + + bool FIRED=FALSE; + + uint32_t TIMER_PERIOD=CONFIG_RETRY; //this variable contains the period for the retransmit Timer + uint8_t MSGSTATE; //this variable defines what the message should be sent when the Timer fires + uint32_t remain; + bool SENT; + uint32_t time=CONFIG_RETRY; + + uint8_t SERVICEREQ_STATE; //Whether Has to retransmit or just Unicast + uint8_t SERVICETYPEREQ_STATE; + struct in6_addr DA_ADDRESSES[MAX_DA_ADDR]; //Array which stores the Directory Agents present in the network + uint8_t DA_Count=0; + + struct in6_addr SRVLOC_DA; //This is the address for receiving UA and SA has to join for receiving DA-ADVT messages + struct in6_addr SRVLOC; //this is the address for receiving Service Type Request and Attribute Type Request messages + struct in6_addr SERVICERequest_IP;//This is the address for receiving service request messages + +/**************************************Messages*******************************************************************************/ + +//Service Request Messages asking for DAAdvt has to be sent to SRVLOC-DA address + +//DA has to send Directory Advertisement to the SRVLOC-DA Address + +//UA has to send the service request messages to a particular IP address based on the function + +/*************************************Functions********************************************************************************/ + + + //Initialize all the IPAddresses here + void init() + { + inet_pton6("ff02::116",&SRVLOC_DA); + inet_pton6("ff02::123",&SRVLOC); + #ifdef NODE_UA + call SSLPNode.setUA(); + #elif NODE_SA + call SSLPNode.setSA(); + #endif + call UDPSend.bind(SSLP_TRANSMIT_PORT); + call UDPReceive.bind(SSLP_LISTENING_PORT); + } + + + /*This function returns the length of the string*/ + uint8_t stringlength(char *data) + { + uint8_t i; + uint8_t count=0; + for(i=0;*(data+i)!='\0';i++) + count++; + return count; + } + + //URL is of the format service:directory-agent://IP + struct in6_addr ExtractIP(char *url) + { + url[stringlength(url)-1]='\0'; + inet_pton6(&url[26],&DA_IP); + return DA_IP; + } + + + /*This function gives the unique sequence number for each SREQ.It will give only from 1 to 5 for now if u want u can increase*/ + uint8_t seq_generator(char *service,char *scope) + { + uint8_t i; + //check whether already there is a sequence number for this combination + + for(i=0;iversion=SSLP_VERSION; + header->msgid=type; + header->seq_no=seq_no; + //printf("\n the sequence number sent is %d",seq_no); + } + + //Add DA into the DA Array + void addDA(struct in6_addr *DA) + { + if(DA_Count==0) + { + DA_AVAILABLE=TRUE; + } + + if(DA_Count>4)&0x0f) | //Adding the version + (((*buffer)>>10)&0x30) | //getting the two bits of msgid + (((*buffer)<<6)&0x3c0) | //getting the four bits of msgid + (((*buffer)>>2)&0xc00) | //getting the flags + (((*buffer)<<4)&0xf000) | //getting the reserved + (((*buffer)<<8)&0xff000000) | //getting the 8 bits of the seq + (((*buffer)>>8)&0x00ff0000) ; //getting the next 8 bits of the sequence number + + hdr=(struct sslp_hdr *)buffer; + return hdr; + } + + + + + +/*****************************************Send Handlers*************************************************************************/ + + //Handler to Send the Service Request Message + int srvrqst_snd(char *service,uint8_t length_service,char *scope,uint8_t length_scope) + { + + service_request_msg *sreq_msg=(service_request_msg *)ip_malloc(sizeof(service_request_msg));//Service Request Message + #ifdef NODE_UA + //Before Sending Lets Check whether any information already exists for this service and scope in the cache + int index=call ServiceLocation.findService(service,scope); + //suppose if the service Location already exist + if(index!=-1) + { + //just move all the services on the top just like sort it with the services will have to do + //TODO:Has to do + return 0; + } + #endif + //no service information exist about that location has to send the service request message to get the info + memset(sreq_msg,0,sizeof(*sreq_msg)); + //we will fill the header with the msg-id set to the SERVICE_REQUEST + fillHeader(&sreq_msg->sslp_header,SERVICE_REQUEST,seq_generator(service,scope)); + + + + //filling the message + //first we will work with IP Address as the Addressing Mode we will implement the remaining later + sreq_msg->AM=IP_ADDR; + + //setting the source address to the Link Local Address formed with EUI-64 + call IPAddress.getLLAddr(&sreq_msg->ip_address); + //adding the "service:" to the service string following the service template + + + + service=addService(service); + //copying the service and scope into the message + memcpy(&sreq_msg->service_type,service,length_service+stringlength("service:")); + + sreq_msg->length_service_type=stringlength(service); + printf("\n Service Request length :%d",sreq_msg->length_service_type); + printfflush(); + memcpy(&sreq_msg->scope,scope,length_scope); + sreq_msg->length_scope_list=stringlength(scope); + //We will Fill the UDP Header(IP+Port) + dest.sin6_port=htons(SSLP_LISTENING_PORT); + //if(!memcmp(&sreq_msg.service_type,"service:directory-agent",stringlength("service:directory-agent"))) + + if(DA_AVAILABLE) + { + memcpy(&dest.sin6_addr,&DA_ADDRESSES[0],sizeof(struct in6_addr)); + SERVICEREQ_STATE=SSLP_UNICAST; + printf("\n as da is present directly unicasting it to da"); + } + else + memcpy(&dest.sin6_addr,&SRVLOC_DA,sizeof(struct in6_addr)); + //else + // inet_pton6("ff02::1",&dest.sin6_addr); //filling the destination address as all-nodes address + //do we have to create a separate address for SA Nodes???? + + + printf("\n sending a service request message with the service type :%s",sreq_msg->service_type); + printf("\n size of the message is %d",sizeof(*sreq_msg)); + printfflush(); + call Leds.led2Toggle(); + call UDPSend.sendto(&dest,sreq_msg,sizeof(*sreq_msg)); + ip_free(sreq_msg); + MSGSTATE=SERVICE_REQUEST; + if(SERVICEREQ_STATE==RETRANSMIT) //It is mainly so that sending a service request for service:directory-agent should not be retransmitted + {//If the message is not received we have to retransmit for that we will use the Timer + call RetransmitTimer.startOneShot(time); + //printf("\n Timer period:%ld",time); + } + if(!FIRED&&memcmp(service,"service:directory-agent",stringlength("service:directory-agent"))) + { + #ifdef NODE_UA //clearing the previous data + memset(&entries,0,sizeof(servicelocation_entry)*STORE_MAX_SEQUENCES); + location_entriescount=0; + call StorageTimer.startOneShot(WAIT_PERIOD_SREPLY); + FIRED=TRUE; + #endif + } + return 0; + } + + //Handler to send the Service Reply Message + #ifdef NODE_SA + void srvrply_snd(service_request_msg *servicemsg,struct sockaddr_in6 *destination,uint16_t error) + { + + char url[48]; + service_reply_msg *srep_msg=(service_reply_msg *)ip_malloc(sizeof(service_reply_msg)); //Service Reply Message + if(call SSLPNode.getServiceURL(removeService(servicemsg->service_type),servicemsg->scope,url)==SUCCESS) + { + printf("\n the service url is %s",url); + } + else{ + printf("\n Error in getting the service url"); + } + //Filling the Service Reply Message Header + fillHeader(&srep_msg->sslp_header,SERVICE_REPLY,servicemsg->sslp_header.seq_no); + + //Filling the Message details + + srep_msg->error_code=error; + srep_msg->location_entry_count=1; //TODO:Make dynamic + + srep_msg->location_entry.lifetime=600; //TODO: Define Macros for this + srep_msg->location_entry.LT=URL_ADDR; //fixing to URL here + srep_msg->location_entry.length_url=stringlength(url); + memcpy(srep_msg->location_entry.url,url,sizeof(url)); + printf("\n location entry :%s",srep_msg->location_entry.url); + printfflush(); + call UDPSend.sendto(destination,srep_msg,sizeof(service_reply_msg)); + ip_free(srep_msg); + + } + + + //Handler to send the Service Registration Message + + void srvreg_snd(servicelocation_entry *location_entry,char *servicetype,char *scope,uint8_t state) + { + serviceregistration *sreg_msg = (serviceregistration *)ip_malloc(sizeof(serviceregistration));//Service Registration Message + memset(sreg_msg,0,sizeof(*sreg_msg)); + //Filling the Service Registration Message Header + fillHeader(&sreg_msg->sslp_header,SERVICE_REGISTRATION,seq_generator(servicetype,scope)); + if(state==FRESH) + sreg_msg->sslp_header.F_flag=1; + //Filling the Message Details + sreg_msg->location_entry=*location_entry; + sreg_msg->length_service_type=stringlength(servicetype)+stringlength("service:"); + //adding the "service:" to the service string following the service template + + servicetype=addService(servicetype); + printf("\n service registering for %s",servicetype); + printfflush(); + memcpy(&sreg_msg->service_type,servicetype,stringlength(servicetype)); + sreg_msg->length_scope_type=stringlength(scope); + memcpy(&sreg_msg->scope,scope,stringlength(scope)); + + //Sending the Message to the DA + + //Fill the Message + dest.sin6_port=htons(SSLP_LISTENING_PORT); + //DA Address + if(DA_AVAILABLE) + { + printf("\n DA is available directly send it to the DA"); + memcpy(&dest.sin6_addr,&DA_ADDRESSES[0],sizeof(struct in6_addr)); + }else{ + inet_pton6("ff02::123",&dest.sin6_addr); + } + //printf("\n sending service registration message with length:%d",sizeof(*sreg_msg)); + + + call UDPSend.sendto(&dest,sreg_msg,sizeof(*sreg_msg)); + ip_free(sreg_msg); + } + + //Handler to send the Service De Registration Message + void srvdereg_snd(servicelocation_entry *location_entry,char *servicetype,char *scope) + { + servicederegistration *sdereg_msg=(servicederegistration *)ip_malloc(sizeof(servicederegistration));//Service De registration Message + memset(sdereg_msg,0,sizeof(*sdereg_msg)); + + //Filling the service deregistration message Header + fillHeader(&sdereg_msg->sslp_header,SERVICE_DEREGISTRATION,seq_generator(servicetype,scope)); + + //Filling the Message Details + + sdereg_msg->location_entry = *location_entry; + sdereg_msg->length_service_type=stringlength(servicetype)+stringlength("service:"); + servicetype=addService(servicetype); + memcpy(&sdereg_msg->service_type,servicetype,stringlength(servicetype)); + sdereg_msg->length_scope_type=stringlength(scope); + memcpy(&sdereg_msg->scope,scope,stringlength(scope)); + + //Sending the Message to the DA + + //Fill the Message + dest.sin6_port=htons(SSLP_LISTENING_PORT); + //DA Address + if(DA_AVAILABLE) + { + printf("\n DA is available directly send it to the DA"); + memcpy(&dest.sin6_addr,&DA_ADDRESSES[0],sizeof(struct in6_addr)); + } + else + { + printf("\n DA is not available we have to multicast it"); + inet_pton6("ff02::123",&dest.sin6_addr); + } + printf("\n sending service deregistration message with length :%d",sizeof(*sdereg_msg)); + printfflush(); + + call UDPSend.sendto(&dest,sdereg_msg,sizeof(*sdereg_msg)); + ip_free(sdereg_msg); + } + + //Handler to send the Service Type Reply Message + + void srvtyperep_send(servicetype_request_msg *msg,uint16_t error_code,struct sockaddr_in6 *destination) + { + + + servicetype_reply_msg *strep_msg=(servicetype_reply_msg *)ip_malloc(sizeof(servicetype_reply_msg)); //Service Type Reply Message + memset(strep_msg,0,sizeof(*strep_msg)); + //Filling the Service Type Reply Message Header + fillHeader(&strep_msg->sslp_header,SERVICE_TYPE_REPLY,msg->sslp_header.seq_no); + + //Filling the Message Details + printf("\n the scope received is %s",msg->scope); + strep_msg->error_code=error_code; + if(call SSLPNode.getSAState()) + memcpy(&strep_msg->servicetype,call SSLPNode.getServices(msg->scope,msg->length_scope_list), + sizeof(strep_msg->servicetype)); + strep_msg->length_servicetype=stringlength(strep_msg->servicetype); + + //Sending the Message + call UDPSend.sendto(destination,strep_msg,sizeof(*strep_msg)); + printf("\n sending service type reply message");printfflush(); + ip_free(strep_msg); + } + + + + + + #else + //Handler to send the Service Type Request Message + + void srvtypereq_send(char *scope) + { + servicetype_request_msg *streq_msg= (servicetype_request_msg *)ip_malloc(sizeof(servicetype_request_msg)); //Service Type Request Message + memset(streq_msg,0,sizeof(*streq_msg)); + //Filling the Service Type Request Header Message + fillHeader(&streq_msg->sslp_header,SERVICE_TYPE_REQUEST,seq_generator("default",scope)); + + //Filling the Message Details + + streq_msg->AM= IP_ADDR; //Fixing it here to the IP Address + call IPAddress.getLLAddr(&streq_msg->ip_address); + streq_msg->length_scope_list = stringlength(scope); + memcpy(&streq_msg->scope,scope,streq_msg->length_scope_list); + + //Filling the UDP Header + + dest.sin6_port=htons(SSLP_LISTENING_PORT); + + if(DA_AVAILABLE) + { + memcpy(&dest.sin6_addr,&DA_ADDRESSES[0],sizeof(struct in6_addr)); + printf("\n as da is present directly unicasting it to da"); + SERVICETYPEREQ_STATE= SSLP_UNICAST; + } + else{ + SERVICETYPEREQ_STATE=RETRANSMIT; + memcpy(&dest.sin6_addr,&SRVLOC,sizeof(struct in6_addr)); + } + printf("\n sending the service type request message"); + printfflush(); + call UDPSend.sendto(&dest,streq_msg,sizeof(*streq_msg)); + ip_free(streq_msg); + MSGSTATE=SERVICE_TYPE_REQUEST; + //If the message is not received we have to retransmit for that we will use the Timer + if(SERVICETYPEREQ_STATE==RETRANSMIT) + call RetransmitTimer.startOneShot(time); + + //TODO:: HAS To change this such that it will unicast the message while sending to DA and should not start the DAtimer + if(!FIRED) + { + //clearing the previous data + memset(&services_received,0,sizeof(services_received)); + call StorageTimer.startOneShot(WAIT_PERIOD_SREPLY); + FIRED=TRUE; + } + } + #endif + + +/*****************************************Receive Handlers**********************************************************************/ + + #ifdef NODE_SA + //Receive Handler for the service Request Message + void srvrqst_rcv(struct sockaddr_in6 *from, void *data) + { + service_request_msg *servicemsg=(service_request_msg *)data; + if(call SSLPNode.getSAState()) + { + printf("\n srvrqst_rcv:%s",servicemsg->service_type); + //check Whether You have the Service or not + switch(call SSLPNode.findService(removeService(servicemsg->service_type),servicemsg->scope)) + { + case SERV_SCOPE : + printf("\ni will send the service reply with the location info"); + //Now we have to send a Service Reply + srvrply_snd(servicemsg,from,NO_ERROR); + break; + + case SERV: + srvrply_snd(servicemsg,from,SCOPE_ERROR); + break; + + case NONE: + printf("service not present :%s",removeService(servicemsg->service_type)); + break; + default: + printf("some error has occurred"); + } + } + else + { + printf("\n Iam UA and i should not process this message"); + return; + } + } + + //Receive Handler for the Service Reply Message + + void srvrply_rcv(struct sockaddr_in6 *from, void *data) + { + + + + } + + + //Receive Handler for the Service Acknowledgement Message + void srvack_rcv(struct sockaddr_in6 *from,void *data) + { + + + + } + + + //Receive Handler for the Service Type Request Message + void srvtyperqst_rcv(struct sockaddr_in6 *from,void *data) + { + + if(call SSLPNode.getSAState()) + { + if(call SSLPNode.servicesPresent(((servicetype_request_msg *)data)->scope)) + //sending a service type reply message + srvtyperep_send((servicetype_request_msg *)data,NO_ERROR,from); + + } + else{ + printf("\n Iam UA and i should not process this message"); + return; + } + + } + + #endif +/****************************************SplitControl Implementation*************************************************************/ + + command error_t SplitControl.start() + { + + running=TRUE; + init(); + if(!(call SSLPNode.getSAState()||call SSLPNode.getUAState())) //If user forgets to set any role by default set it to UA + call SSLPNode.setUA(); + + #warning "*** SSLP does not start the radio ***" + SERVICEREQ_STATE=SSLP_UNICAST; + //srvrqst_snd("directory-agent",stringlength("directory-agent"),"",0); + call DelayTimer.startOneShot(CONFIG_REG_ACTIVE); //Wait to register services on Active DA discovery + + return SUCCESS; + + } + + + command error_t SplitControl.stop() + { + running= FALSE; + call RadioControl.stop(); + + } + + + + +/******************************************ServiceLocation Implementation******************************************************/ + + #ifdef NODE_UA + //return -1 when no service and scope are matching,else returns the index where the service is present + command int ServiceLocation.findService(char *service,char *scope) + { + int index=servicefinder(service,scope); + if(index!=-1) + { + return index; + } + else + return -1; + } + + //UA specifies the type of the service he want and the scope then we will signal him back with the service Location + command error_t ServiceLocation.findServices(char *service,char *scope) + { + if(call SSLPNode.getUAState()) //Only UA should be able to send the service request message + { + + //clearing the global varaibles to remove the old data and the service request message + memset(&global_service,0,sizeof(global_service)); + memset(&global_scope,0,sizeof(global_scope)); + + //copying the data so that it can be used for retransmission + memcpy(&global_service,service,stringlength(service)); + memcpy(&global_scope,scope,stringlength(scope)); + + global_service_len=stringlength(global_service); + global_scope_len=stringlength(global_scope); + printf("\n setting the state to retransmit"); + printfflush(); + SERVICEREQ_STATE=RETRANSMIT; //It means to retransmit the message if no reply is received + srvrqst_snd(global_service,global_service_len,global_scope,global_scope_len); + return SUCCESS; + } + return FAIL; + + } + + + command error_t ServiceLocation.findAllServices(char *scope) + { + //Send a Service Type Request Message + memset(&global_scope,0,sizeof(global_scope)); + + memcpy(&global_scope,scope,stringlength(scope)); + srvtypereq_send(scope); + return SUCCESS; + } + + #else + command error_t ServiceLocation.registerService(servicelocation_entry *location_entry,char *servicetype,char *scope,uint8_t state) + { + + //Send a Service Registration Message + srvreg_snd(location_entry,servicetype,scope,state); + return SUCCESS; + + } + + command error_t ServiceLocation.deregisterService(servicelocation_entry *location_entry,char *servicetype,char *scope) + { + //Send a Service Deregistration Message + printf("\n sending a service deregistration message"); + srvdereg_snd(location_entry,servicetype,scope); + return SUCCESS ; + + } + + #endif + + + + +/********************************************EVENTS****************************************************************************/ + + + + event void UDPSend.recvfrom(struct sockaddr_in6 *from, void *data, + uint16_t len, struct ip6_metadata *meta) { + struct sslp_hdr *header=(struct sslp_hdr *)data; + #ifdef NODE_UA + service_reply_msg *srep; + #else + service_ack_msg *sack; + #endif + printf("\n the sequence number is %d",header->seq_no); + + switch(header->msgid){ + #ifdef NODE_UA + case SERVICE_REPLY: + srep=(service_reply_msg *)data; + TIMER_PERIOD=CONFIG_RETRY; + + if(srep->location_entry.length_url) + { + printf("\n service reply message is received with length :%d",srep->location_entry.length_url); + addServiceURL(&srep->location_entry); + printf("\n url is %s",srep->location_entry.url); + } + else{ + printf("service reply message is received with zero entries and errorcode:%d",srep->error_code); + } + call RetransmitTimer.stop(); + //Add into an array and after some time signal it back + printfflush(); + break; + #else + case SERVICE_ACKNOWLEDGE: + sack = (service_ack_msg *)data; + printf("\n Service Acknowledge message is received with error code:%d",sack->error_code); + printfflush(); + break; + #endif + default : + printf("\n some other message is received with id:%d",header->msgid); + break; + } + } + + event void UDPReceive.recvfrom(struct sockaddr_in6 *from, void *data, + uint16_t len, struct ip6_metadata *meta) { + + + struct sslp_hdr *header; + printf_in6addr(&from->sin6_addr); + if(call IPAddress.isLLAddress(&from->sin6_addr)) + { + //printf("\n local address"); + //printfflush(); + //header=(struct sslp_hdr *)data; + } + else{ + //printf("\n globaladdress"); + //printf_in6addr(&from->sin6_addr); + //header=getHeader(data); + //printfflush(); + } + header=getHeader(data); + printf("\n the sequence number receive is %d",header->seq_no); + //printf("\n checking the type of the message received"); + if(header->msgid==DA_ADVERTISEMENT) + { + directory_advt_msg *msg = (directory_advt_msg *)data; + struct in6_addr DA_Addr=ExtractIP(msg->location_entry.url); + + printf("\nDA Advertisement Message is received"); + printf("\nURL :%s",msg->location_entry.url); + printf("\n DA_ADDRESS:"); + printf_in6addr(&DA_Addr); + printf("\n scope is %s",msg->scope); + printfflush(); + //add this DA Address into the array of DA_Addresses + + addDA(&DA_Addr); + + } + #ifdef NODE_SA + else if(header->msgid==SERVICE_TYPE_REQUEST) + { + servicetype_request_msg *msg=(servicetype_request_msg *)data; + printf("\n Service Type Request Message is Received"); + printf("\n scope received is %s",msg->scope); + printfflush(); + srvtyperqst_rcv(from,data); + } + else if(header->msgid==SERVICE_REQUEST) + { + printf("\n Service Request Message is received"); + srvrqst_rcv(from,data); + }else if(header->msgid==SERVICE_ACKNOWLEDGE) + { + call Leds.led2Toggle(); + } + #else + else if(header->msgid==SERVICE_TYPE_REPLY) + { + servicetype_reply_msg *strep=(servicetype_reply_msg *)data; + TIMER_PERIOD=CONFIG_RETRY; + call RetransmitTimer.stop(); + addServiceType(strep->servicetype); + printf("\n Service Type Reply Message is received with services:%s",strep->servicetype); + } + #endif + else + { + printf("\n some other message is received with message id :%d",header->msgid); + printf("\n length of the message is %d",len); + //call Leds.led2Toggle(); + } + + } +/*******************************************Timer Functions*********************************************************************/ + + void chooseInterval() + { + + + SENT=TRUE; + if(TIMER_PERIOD==CONFIG_MC_MAX) + return; + + TIMER_PERIOD*=2; + if(TIMER_PERIOD>CONFIG_MC_MAX) + TIMER_PERIOD=CONFIG_MC_MAX; + + time=TIMER_PERIOD; + time/=2; + time+=call Random.rand32()%time; + if(MSGSTATE==SERVICE_REQUEST){ + //printf("\nTimerfired:global_service:%s",global_service); + srvrqst_snd(global_service,global_service_len,global_scope,global_scope_len); + } + #ifdef NODE_UA + else if(MSGSTATE==SERVICE_TYPE_REQUEST){ + srvtypereq_send(global_scope); + } + #endif + } + + + void remainInterval() + { + SENT=FALSE; + remain=TIMER_PERIOD-time; + call RetransmitTimer.startOneShot(remain); + } + + + + +/**********************************************Timer Events**********************************************************************/ + event void RetransmitTimer.fired() //Section6.3(RFC2608) Retransmission of SSLP Messages + { + printf("\n retransmit timer fired"); + if(SENT) + { + remainInterval(); + } + else + { + chooseInterval(); + } + + + } + event void PrintTimer.fired() + { + /*uint8_t i; + for(i=0;i +interface SSLPNode +{ + + + command error_t setUA(); + + command bool getUAState(); + + command error_t setSA(); + + command bool getSAState(); + + #ifdef NODE_SA + + //add services to the services advertised by the SA + command error_t addService(char *service,char *scope,char *url,uint16_t lifetime); + + //remove services from the services advertised by the SA + + command error_t removeService(char *service,char *scope,char *url); + #endif + + //get the services advertised by the SA + + command char * getServices(char *service,uint16_t len); + + + //check whether any services matching to the scope are present + + command bool servicesPresent(char *scope); + + //Get the service URL for the service type + command error_t getServiceURL(char *servicetype,char *scope,char *serviceurl); + + + + //change the scope of the existing service + + command error_t changeScope(char *service,char *new_scope); + + //check whether the service and scope exist or not if the scope is not defined then check whether only the service is present + command uint8_t findService(char *service,char *scope); + + #ifdef PRINTFUART_ENABLED + command error_t printServices(); + #endif + + + + + + + +} diff --git a/tos/lib/net/sslp/SA_UA/SSLPNodeC.nc b/tos/lib/net/sslp/SA_UA/SSLPNodeC.nc new file mode 100755 index 0000000000..e8e95795fe --- /dev/null +++ b/tos/lib/net/sslp/SA_UA/SSLPNodeC.nc @@ -0,0 +1,17 @@ + +configuration SSLPNodeC{ + provides interface SSLPNode; +} + +implementation{ + + components SSLPNodeP; + components SSLC; + SSLPNode=SSLPNodeP; + SSLPNodeP.ServiceLocation->SSLC; + #ifdef NODE_SA + components new TimerMilliC() as Timer; + SSLPNodeP.Timer -> Timer; + #endif + +} diff --git a/tos/lib/net/sslp/SA_UA/SSLPNodeP.nc b/tos/lib/net/sslp/SA_UA/SSLPNodeP.nc new file mode 100755 index 0000000000..46bd9c8c74 --- /dev/null +++ b/tos/lib/net/sslp/SA_UA/SSLPNodeP.nc @@ -0,0 +1,405 @@ + +#include + +module SSLPNodeP +{ + provides interface SSLPNode; + uses interface ServiceLocation; + #ifdef NODE_SA + uses interface Timer; + #endif + +} + +implementation +{ + + uint8_t DAState=FALSE; + uint8_t SAstate=FALSE,UAstate=FALSE; + char DA_SCOPE[10]; + services_available sa_services[MAX_SERVICE_ADVERTISE]; + char Services[40]; + uint8_t REGISTRATION_STATE; + /*This function returns the length of the string*/ + uint8_t stringlength(char *data) + { + uint8_t i; + uint8_t count=0; + for(i=0;*(data+i)!='\0';i++) + count++; + return count; + + } + //function that returns the index + int allocindex() + { + int index; + for(index=0;index +@version $Revision: 1.0 + +*/ + +#ifndef SSLP_H +#define SSLP_H + +#include + +struct sslp_hdr{ + uint8_t version:4; //contains the version of the sslp being used + uint8_t msgid:6; //determines the message type + uint8_t O_flag:1; //O(Overflow) flag is set when the message length exceeds what can fit into the datagram + uint8_t F_flag:1; //F(Fresh) flag is set on every SREG + uint8_t rsv:4; //reserved + uint16_t seq_no; //set to a unique value for each unique SREQ message.If the request message is retransmitted,the same sequence number is used.Replies set the sequence number to the same value as the sequence number in the SREQ message. +}__attribute__((packed)); + + +//service request message +/*Service Request Messages are sent by UA to SA to get the location of service specified in the service type*/ +typedef struct service_request_msg{ + struct sslp_hdr sslp_header; //header with message-id=1 + uint8_t AM:2; //addressing mode specifies the size of the source address + uint8_t reserved:6; + uint8_t reserved1; //for padding + struct in6_addr ip_address; //we are fixing the AM mode to IP Address here + uint16_t length_service_type; + char service_type[24]; //services should be defined according to the service template + uint16_t length_scope_list; + char scope[16]; +}__attribute__((packed))service_request_msg; + + +//sslp -draft + + + +typedef struct servicelocation_entry{ + uint16_t lifetime; + uint8_t LT:2; + uint8_t reserved:6; + uint16_t length_url; + char url[80]; //TODO:CHANGE at pc to 24 from 48 //make sure while sending from pc u have to append "*" so that overwritten of data does not takes place..A service of a particular type announces its availability with a service:url that includes a domain name or ip address,and possibly its port number and optionally basic configuration parameters +}__attribute__((packed))servicelocation_entry; + +//service Reply Message + +typedef struct service_reply_msg{ + struct sslp_hdr sslp_header; //header with message-id=2 + uint16_t error_code; + uint16_t location_entry_count; + servicelocation_entry location_entry; +}__attribute__((packed))service_reply_msg; + +//Service Registration Message + +typedef struct serviceregistration{ + struct sslp_hdr sslp_header; + + servicelocation_entry location_entry; + + uint16_t length_service_type; + char service_type[24]; + uint16_t length_scope_type; + char scope[16]; +}__attribute__((packed))serviceregistration; + + +//Service Deregistration Message +//Used for deregistering a service present +typedef struct servicederegistration { + struct sslp_hdr sslp_header; //header with message id is 9 + + servicelocation_entry location_entry; + uint16_t length_service_type; + char service_type[24]; + uint16_t length_scope_type; + char scope[12]; +}__attribute__((packed))servicederegistration; + + + +//service type request message is used by UA to get all the services present in the network +typedef struct servicetype_request_msg{ + struct sslp_hdr sslp_header; //header with message id=7 + uint8_t AM:2; + uint8_t reserved:6; + uint8_t reserved1; + struct in6_addr ip_address; //we are fixing the AM mode to IP Address here + uint16_t length_scope_list; + char scope[16]; +}__attribute__((packed))servicetype_request_msg; + + +//service Type Reply Message +//message send in response to Service Type Request + +typedef struct servicetype_reply_msg { + struct sslp_hdr sslp_header; + uint16_t error_code; + uint16_t length_servicetype; + char servicetype[40]; +}__attribute__((packed))servicetype_reply_msg; + + +//Directory Advertisement Message +//Message sent by DA in response to a Service Request Message with service type:service:directory-agent or periodically it sends a unsolicited message to inform that he is present in the network + +typedef struct Directory_Advt_msg { + struct sslp_hdr sslp_header; + uint16_t error_code ; //error_code should be sent to zero when DA broadcasts + servicelocation_entry location_entry; //url should contain service:directory-agent://" of the DA" + uint16_t length_scope_list; + char scope[8]; //the scope list of the DA must not be null +}__attribute__((packed))directory_advt_msg; + + + + +//Service Acknowledgement Messages + +typedef struct service_ack_msg{ + struct sslp_hdr sslp_header; + uint16_t error_code; +}__attribute__((packed))service_ack_msg; + + + +//Service Acknowledgement Messages(SACK) are received in response to the SREG messages +typedef struct { + char service[16]; + char url[48]; + char scope[16]; + uint16_t lifetime; +}__attribute__((packed))services_available; + +//Storing the registered services in the datastructure + +typedef struct reg_services{ + char servicetype[24]; + uint16_t lifetime; + char url[48]; + char scope[16]; +}__attribute__((packed))reg_services; + + +typedef struct { + char service[16]; + char scope[16]; + uint8_t sequence_no; +}__attribute__((packed))sequencer; + +enum{ + + NO, + YES, +}; + +enum { +RETRANSMIT=1, +SSLP_UNICAST=2, +FRESH=3, +RENEW=4, +}; + +//error types + +enum{ + NO_ERROR=0, + PARSING_ERROR=1, + SCOPE_ERROR=2, + INTERNAL_ERROR=3, + MSG_NOT_SUPPORTED=4, + ILLEGAL_REGISTRATION=5, + DA_BUSY=6, +}; +//Addressing Mode Types + +enum{ + + SHORT_ADDR=1, + EXTENDED_ADDR=2, + IP_ADDR=3, + URL_ADDR=3, +}; + +//Return Types + +enum{ + SERV_SCOPE=1, //Both service and Scope Matches + SERV=2, //Only Service Matches + NONE=3, //None Matches +}; +//Message Types + + +enum{ + SERVICE_REQUEST=1, + SERVICE_REPLY=2, + SERVICE_REGISTRATION=3, + SERVICE_ACKNOWLEDGE=4, + DA_ADVERTISEMENT=5, + SA_ADVERTISEMENT=6, + SERVICE_TYPE_REQUEST=7, + SERVICE_TYPE_REPLY=8, + SERVICE_DEREGISTRATION=9, +}; + +#define SSLP_VERSION 2 +/*(Section 5.3 of RFC2608)Request which fails to give a response are retransmitted. The initial retransmissions occurs after a CONFIG_RETRY wait period.Retransmissions must be made with exponentially increasing wait intervals(doubling the wait each time) +Multicast requests should be reissued over CONFIG_MC_MAX seconds untill a result has been obtained +*/ + + +#define CONFIG_DA_BEAT 10800000U //3 Hours +//CONFIG_DA_BEAT is the interval after which DA sends unsolicited Directory Advertisements Messages so that SA and UA can recognize that there is a DA in the network +#define CONFIG_RETRY 2000U //2 Seconds +#define CONFIG_MC_MAX 15000U //15 Seconds + +#define STORE_MAX_SERVICES 5 //Maximum amount of services we can store +#define STORE_MAX_SEQUENCES 5 //Maximum amount of sequencese we can store +#define WAIT_PERIOD_SREPLY 10000U //Maximum amount of time we will wait for service reply if messages received after this will be discarded +#define PRINTTIMER_PERIOD 5000U //delay between each print +#define MAX_SERVICE_ADVERTISE 3 //Maximum services the SA can advertise + +#define SSLP_LISTENING_PORT 4270 //According to RFC 2608(Section 6.1) +#define SSLP_TRANSMIT_PORT 427 //SLP +#define MAX_DA_ADDR 3 //Maximum number of DA Addresses that can be stored +#define CONFIG_REG_ACTIVE 3000 //Wait to register services on passive DA discovery + +#endif