📄 generaterpc.pl
字号:
$greenToggle if ( sendingResponse == TRUE ) { dbg(DBG_USR2, "stopped processing because sending\\n"); post processCommand(); $yellowToggle return; } if ( processingCommand == TRUE ) { dbg(DBG_USR2, "stopped processing because already processing\\n"); $yellowToggle return; } else { processingCommand = TRUE; } /*fill in the response message headers*/ responseMsg->transactionID = msg->transactionID; responseMsg->commandID = msg->commandID; responseMsg->sourceAddress = TOS_LOCAL_ADDRESS; responseMsg->errorCode = RPC_SUCCESS; responseMsg->dataLength = 0; if( (id < $num_rpcs) && (msg->dataLength != args_sizes[id]) ) { responseMsg->errorCode = RPC_GARBAGE_ARGS; dbg(DBG_USR2, "param size doesn't match\\n"); } else if( (id < $num_rpcs) && (return_sizes[id] + sizeof(RpcResponseMsg) > maxLength) ) { responseMsg->errorCode = RPC_RESPONSE_TOO_LARGE; dbg(DBG_USR2,"Return type is too large for the response packet"); } else switch( id ) {EOF#this is the heart of rpc: parse the args, call the func, pack the returnfor $fullName (sort keys %rpcFunctions ) { $rpc = $rpcFunctions{$fullName}; $params = $rpc->{'params'}; $s = sprintf "%s\n /*** $fullName ***/\n", $s; $s = sprintf "%s case $rpc->{'commandID'}: {\n", $s; #get ready with a returnVal decl if necessary if ( $rpc->{'returnType'}->{'typeName'} ne 'void') { my $ptr = $rpc->{returnType}{typeClass} eq 'pointer' ? "*" : ""; $s .= " $rpc->{returnType}{typeName}$ptr RPC_returnVal;\n"; } #setup the parameters for ( $count=0 ; $count < $rpc->{'numParams'} ; $count++) { $s = sprintf "%s %s RPC_%s;\n", $s, $params->{"param$count"}->{'type'}->{'typeName'}, $params->{"param$count"}->{'name'}; } $s = sprintf "%s dbg(DBG_USR2, \"handling commandId $rpc->{'commandID'}\\n\");\n",$s; for ( $count=0 ; $count < $rpc->{"numParams"} ; $count++) { my $name = "RPC_" . $params->{"param$count"}{name}; my $type = $params->{"param$count"}{type}{typeName}; $s .= " memcpy( &$name, byteSrc, sizeof($type) );\n"; $s .= " byteSrc += sizeof($type);\n" if $count != ($rpc->{numParams}-1); } #store the return value appropriately $s = sprintf "%s ", $s; if ( $rpc->{'returnType'}->{'typeName'} ne 'void') { $s .= "RPC_returnVal = "; } #"call" commands or "signal" events if ($rpc->{'functionType'} eq "command"){ $s = sprintf "%scall", $s; } elsif ($rpc->{'functionType'} eq "event"){ $s = sprintf "%ssignal", $s; } #actually invoke the function with arguments $s = sprintf "%s $rpc->{'componentName'}_",$s; if ( $rpc->{'interfaceName'} ){ $s = sprintf "%s$rpc->{'interfaceName'}.", $s; } $s = sprintf "%s$rpc->{'functionName'}( ", $s; for ( $count=0; $count < $rpc->{'numParams'} ; $count++) { my $str = "RPC_".$params->{"param$count"}->{'name'}; $str = "&$str" if $params->{"param$count"}{type}{typeClass} eq "pointer"; $s .= " $str,"; } $s = sprintf "%s\b );\n", $s; #store the return value, if necessary if ( $rpc->{returnType}{typeName} ne 'void') { my $rvArg = ($rpc->{returnType}{typeClass} eq 'pointer' ? "" : "&") . "RPC_returnVal"; $s .= " memcpy( &responseMsg->data[0], $rvArg, sizeof($rpc->{returnType}{typeName}) );\n"; } $s = sprintf "%s dbg(DBG_USR2, \"done calling the functions\\n\");\n",$s; #mark the size of the return value if ( $rpc->{'returnType'}->{'typeName'} ne 'void' ){ $s = sprintf "%s responseMsg->dataLength = sizeof ( %s ); dbg(DBG_USR2, \"responseMsg->dataLength = %s\\n\", responseMsg->dataLength); dbg(DBG_USR2, \" sizeof ( %s )= %s\\n\", sizeof ( %s )); } break;", $s, $rpc->{'returnType'}->{'typeName'}, $d, $rpc->{'returnType'}->{'typeName'}, $d, $rpc->{'returnType'}->{'typeName'}; } else { $s = sprintf "%s dbg(DBG_USR2, \"not packing void return value\\n\"); } break;", $s; }}#phew!$s = sprintf "%s default: dbg(DBG_USR2, \"found no rpc function\\n\"); responseMsg->errorCode = RPC_PROCEDURE_UNAVAIL; } /*** now send the response message off if necessary ***/ dbg(DBG_USR2, \"errorCode=%s,dataLength=%s\\n\",responseMsg->errorCode, responseMsg->dataLength); dbg(DBG_USR2, \"sizeof( RpcResponseMsg ) = %s, data-transactionID= %s\\n\",sizeof (RpcResponseMsg),((uint32_t)&(responseMsg->data[0]) - (uint32_t)&(responseMsg->transactionID))); /* if (responseMsg->errorCode == RPC_SUCCESS && responseMsg->dataLength==0){ dbg(DBG_USR2, \"done processing, no return args\\n\"); processingCommand=FALSE; } else if (responseMsg->errorCode == RPC_SUCCESS){ //calculate the size to be the size of the data I just added //plus the size of the responseMsg less the data array (the data array //can sometimes take space due to compiler packing) if (call ResponseSendMsgDrain.send(msg->returnAddress, responseMsg->dataLength + ( (uint32_t)&(responseMsg->data[0]) - (uint32_t)&(responseMsg->transactionID)), responseMsgPtr) ){ dbg(DBG_USR2, \"sending response\\n\"); sendingResponse=TRUE; } else{ dbg(DBG_USR2, \"sending response failed\\n\"); processingCommand=FALSE; } } else{*/ if (msg->responseDesired == 0){ dbg(DBG_USR2, \"no response desired; not sending response message\"); processingCommand=FALSE; } else if (call ResponseSendMsgDrain.send(msg->returnAddress, responseMsg->dataLength + sizeof(RpcResponseMsg), responseMsgPtr) ){ dbg(DBG_USR2, \"sending response\\n\"); sendingResponse=TRUE; $redToggle } else{ dbg(DBG_USR2, \"sending response failed\\n\"); processingCommand=FALSE; $yellowToggle }// } dbg(DBG_USR2, \"done processing.\\n\"); } event TOS_MsgPtr CommandReceiveDrip.receive(TOS_MsgPtr pMsg, void* payload, uint16_t payloadLength) { RpcCommandMsg* msg = (RpcCommandMsg*)payload; dbg(DBG_USR2, \"received drip command message\\n\"); //store the drip message for later drip rebroadcasting memcpy(dripStore.data, payload, payloadLength); dripStoreLength = payloadLength; //if it is destined to us, post a task to process it if (msg->address == TOS_LOCAL_ADDRESS || msg->address == TOS_BCAST_ADDR ) { //store another copy for later processing memcpy(cmdStore.data, payload, payloadLength); cmdStoreLength = payloadLength; if (post processCommand() == SUCCESS){ dbg(DBG_USR2, \"posted task\\n\"); } else{ dbg(DBG_USR2, \"failed to post task\\n\"); } } else { dbg(DBG_USR2, \"not posting task because not for me\\n\"); } return pMsg; } event TOS_MsgPtr CommandReceiveLocal.receive(TOS_MsgPtr pMsg) { //store the drip message for later processing dbg(DBG_USR2, \"received local command message, len=%s\\n\",pMsg->length); memcpy(cmdStore.data, pMsg->data, pMsg->length); cmdStoreLength = pMsg->length; if (post processCommand() == SUCCESS){ dbg(DBG_USR2, \"posted task\\n\"); } else{ dbg(DBG_USR2, \"failed to post task\\n\"); } return pMsg; } event result_t CommandDrip.rebroadcastRequest(TOS_MsgPtr msg, void *payload) { dbg(DBG_USR2, \"drip rebroadcast request\\n\"); memcpy(payload, dripStore.data, dripStoreLength); call CommandDrip.rebroadcast(msg, payload, dripStoreLength); return SUCCESS; } event result_t DrainSend.sendDone(TOS_MsgPtr pMsg, result_t success) { dbg(DBG_USR2, \"wtf!! drainSend send done\\n\"); return SUCCESS; } event result_t ResponseSendMsgDrain.sendDone(TOS_MsgPtr pMsg, result_t success) { if (success == SUCCESS) { dbg(DBG_USR2, \"drain send done: SUCCESS\\n\"); } else{ dbg(DBG_USR2, \"drain send done: FAIL\\n\"); } processingCommand = FALSE; sendingResponse = FALSE; return SUCCESS; }/* event result_t ErrorSendMsgDrain.sendDone(TOS_MsgPtr pMsg, result_t success) { if (success == SUCCESS) { dbg(DBG_USR2, \"drain error send done: SUCCESS\\n\"); } else{ dbg(DBG_USR2, \"drain error send done: FAIL\\n\"); } processingCommand = FALSE; sendingResponse = FALSE; return SUCCESS; }*/", $s, $d, $d, $d, $d, $d;#now, print out all the provided events or uses commands that are requiredfor my $requiredFunc (values %requiredFunctions) { $s .= sprintf(" %s %s %s.%s( ", $requiredFunc->{functionType}, $requiredFunc->{returnType}->{typeDecl}, $requiredFunc->{componentName}."_".$requiredFunc->{interfaceName}, $requiredFunc->{functionName}); for my $param (values %{$requiredFunc->{params}}) { $s .= " $param->{type}->{typeDecl} $param->{name},"; } $s .= "\b) { }\n";}$s .= "\n}";#send the generated code out to a filemy $backsp = sprintf "\b";$s =~ s/.$backsp//g;open(RPCM, ">${DestDir}RpcM.nc");print RPCM "$G_warning$s";close(RPCM);############################### Generate the RpcC.nc file##############################$s = "includes Rpc;configuration RpcC { provides { interface StdControl; }}implementation { components RpcM, GenericComm, DrainC, DestC, DripC, $LedsC DripStateC;";# generate the declarations of each rpc interface or function:my %components;for $fullName (sort keys %rpcFunctions ) { $rpc = $rpcFunctions{$fullName}; if (! $components{$rpc->{'componentName'}}){ $components{$rpc->{'componentName'}} = 1; $s = sprintf "%s\n components $rpc->{'componentName'};", $s; }}my %componentInterfaces;for $fullName (sort keys %rpcFunctions ) { my $rpc = $rpcFunctions{$fullName}; if ( $rpc->{'interfaceName'} ){ if (! $componentInterfaces{$rpc->{'componentName'}.$rpc->{'interfaceName'}}){ $componentInterfaces{$rpc->{'componentName'}.$rpc->{'interfaceName'}} = 1; $s = sprintf "%s\n RpcM.$rpc->{'componentName'}_$rpc->{'interfaceName'}", $s; if ($rpc->{'provided'}==1){ $s = sprintf "%s -> ", $s; } else{ $s = sprintf "%s <- ", $s; } $s = sprintf "%s$rpc->{'componentName'}.$rpc->{'interfaceName'};", $s; } } else{ $s = sprintf "%s\n RpcM.$rpc->{'componentName'}_$rpc->{'functionName'}", $s; if ($rpc->{'provided'}==1){ $s = sprintf "%s -> ", $s; } else{ $s = sprintf "%s <- ", $s; } $s = sprintf "%s$rpc->{'componentName'}.$rpc->{'functionName'};", $s; }}$s = sprintf "%s //now do all the wiring for the rpc communication: StdControl = RpcM; $ledsWiring RpcM.SubControl -> GenericComm; RpcM.SubControl -> DrainC; RpcM.SubControl -> DripC; //genericComm wiring RpcM.CommandReceiveLocal -> GenericComm.ReceiveMsg[AM_RPCCOMMANDMSG]; //drip wiring RpcM.CommandReceiveDrip -> DripC.Receive[AM_RPCCOMMANDMSG]; RpcM.CommandDrip -> DripC.Drip[AM_RPCCOMMANDMSG]; DripC.DripState[AM_RPCCOMMANDMSG] -> DripStateC.DripState[unique(\"DripState\")]; RpcM.Dest -> DestC; //drain wiring RpcM.ResponseSendMsgDrain -> DrainC.SendMsg[AM_RPCRESPONSEMSG];// RpcM.ErrorSendMsgDrain -> DrainC.SendMsg[AM_RPCERRORMSG]; RpcM.DrainSend -> DrainC.Send[AM_RPCRESPONSEMSG];}", $s;#send the generated code out to a file$s =~ s/.$backsp//g;open(RPCC, ">${DestDir}RpcC.nc");print RPCC "$G_warning$s";close(RPCC);############################# Substitute abstract params# This function is only here to pass a hashref by value############################sub substituteAbstractParams{ my ($params, $typeNames, $typeVals) = @_; my %newParams = (); my $i = 0; for my $name (keys %{$params}) { my $param = $params->{$name}; my %newParam = (); $newParam{'name'} = $param->{'name'}; $newParam{'type'} = &substituteAbstractTypes($param->{'type'}, $typeNames, $typeVals); $newParams{$name} = \%newParam; $i++; } return \%newParams;} ############################# Match a type with an abstract type definition and, if it matches# substitute the type parameter used when the interface was declared############################sub substituteAbstractTypes{ my ($type, $typeNames, $typeVals) = @_; my $i = 0; for my $typeName (@{$typeNames}) { if ( $type->{typeName} eq $typeName ) { return &NescParser::parseType($typeVals->[$i]); } $i++; } return $type}############################## check the following criteria of any rpc function:# 1. any provided rpc interface has only commands# 2. any used rpc interface has only events# 3. all rpc commands and events are provided# 4. no rpc function has void* param or return types# 5. no rpc function defined in generic modules##############################sub checkRpcFunction { my ($rpc, $fullName) = @_; #if this is an interface function, provided/used depends on command/event if ( $rpc->{'interfaceName'}){ if ($rpc->{'provided'}==1 && $rpc->{'functionType'} eq 'event'){ print "WARNING: rpc function $fullName is an event in a provided interface; it is now being handled by RpcM.\n"; return 1; } elsif ( $rpc->{'provided'}==0 && $rpc->{'functionType'} eq 'command'){ print "WARNING: rpc function $fullName is a command in a used interface; it is now being handled by RpcM.\n"; return 1; } } #if this is a function not in an interface, it must be provided else{ if ($rpc->{'provided'}==0 ){ print "ERROR: rpc function $fullName is used; it cannot be tagged \@rpc.\n"; $shouldDie = 1; } } if ( $rpc->{'returnType'}->{'typeName'} eq 'void' && $rpc->{'returnType'}->{'typeClass'} eq 'pointer'){ print "ERROR: rpc function $fullName returns a void*.\n"; $shouldDie = 1; } for my $param (values %{$rpc->{'params'}}){ if ($param->{'type'}->{'typeName'} eq 'void' && $param->{'type'}->{'typeClass'} eq 'pointer'){ print "ERROR: rpc function $fullName has a void* parameter.\n"; $shouldDie = 1; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -