📄 obex.c
字号:
if (!getAnswer) return OBX_RC_ERR_INAPPROPRIATE; if (!(request = iobxObjectNew())) { OBXDBGERR(("[ERROR] ObxGetSend() Error creating request object")); return OBX_RC_ERR_MEMORY; } while (!done) { OBXDBGINFO(("ObxGetSend() waiting for request\n")); if ((rc=iobxObjectReset(request)) != OBX_RC_OK) { OBXDBGERR(("[ERROR] ObxGetSend() iobxObjectReset failed with code 0x%x\n",rc)); iobxObjectFree(request); return rc; } if ((rc=iobxObjectRecvObject(request, handle)) != OBX_RC_OK) { OBXDBGERR(("[ERROR] ObxGetSend() bad returncode from iobxObjectRecvObject\n")); iobxObjectFree(request); return rc; }//Check if the headers of ConnectionID and Type carried by Get command are legal. if ( (obxlist=iobxObjectGetHeaderList( request )) ) { if ( (obxiterator=iobxListGetIterator( obxlist )) ) { iobxIteratorReset( obxiterator ); while ( iobxIteratorHasNext( obxiterator ) ) { if ( (obxheader = (ObxHeader *)iobxIteratorNext( obxiterator )) ) { switch(obxheader->identifier) { case OBEX_HEADER_CONNECTION: OBXDBGINFO(("OBX ObxGetSend() The ConnectionID carried in request command is %d and the one we assign is %d\n", obxheader->value.fourBytevalue, handle->OBEXConnectionID )); if(obxheader->value.fourBytevalue!=handle->OBEXConnectionID) return OBX_RC_ERR_SML_CONNECTIONID_HDR; connectionIDHeaderCount++; break; case OBEX_HEADER_TYPE: length = iobxBufSize(obxheader->value.byteSequenceValue); buffer = (unsigned char *)malloc( length+1 ); memset(buffer,0,length+1); iobxBufRead( obxheader->value.byteSequenceValue, buffer, length ); OBXDBGINFO(("OBX ObxGetSend() Prefered Mime Type is \'%s\'\n", buffer )); if(strcmp((const char *)buffer, (const char *)mimeType)) return OBX_RC_ERR_SML_TYPE_HDR; free(buffer); typeHeaderCount++; break; } } } iobxIteratorFree( obxiterator ); } else { OBXDBGERR(("[ERROR] ObxTransactionRecv() bad return code from iobxListGetIterator(), rc=%d\n", rc)); return rc; } } else { OBXDBGERR(("[ERROR] ObxTransactionRecv() bad return code from iobxObjectGetHeaderList(), rc=%d\n", rc)); return rc; } //Every Get command must have final bit set./* if (request->cmd != OBEX_CMD_GET) { if ((request->cmd & ~OBEX_CMD_FINAL) != OBEX_CMD_GET) { OBXDBGERR(("[ERROR] ObxGetSend() unexpected command received (0x%02x)\n",request->cmd)); iobxObjectFree(request); return OBX_RC_ERR; } }*/ if (request->cmd != ( OBEX_CMD_GET | OBEX_CMD_FINAL) ) { OBXDBGERR(("[ERROR] ObxGetSend() unexpected command received (0x%02x)\n",request->cmd)); iobxObjectFree(request); return OBX_RC_ERR; } if ((rc=iobxObjectSendObject(getAnswer, handle)) != OBX_RC_OK) { OBXDBGERR(("[ERROR] ObxGetSend() bad returncode from iobxObjectSendObject (0x%x)\n",rc)); iobxObjectFree(request); return rc; }//The last response of Get command have response code of 0xA0, i.e. OBEX_RSP_SUCCESS | OBEX_CMD_FINAL.// if (getAnswer->cmd & OBEX_CMD_FINAL) { if (getAnswer->cmd == (OBEX_RSP_SUCCESS | OBEX_CMD_FINAL)) { done = TRUE; } }//There must be Type header carried in Get command. if(typeHeaderCount!=1) return OBX_RC_ERR_SML_TYPE_HDR;//There must be ConnectionID header carried in Get command. if(connectionIDHeaderCount!=1) return OBX_RC_ERR_SML_CONNECTIONID_HDR; return rc;}OBEX_EXPORT ObxRc ObxGetRecv(ObxHandle *handle, ObxObject *request, ObxObject *responseOut ) { short done = FALSE; ObxRc rc = OBX_RC_OK; ObxObject *response = NULL; ObxIterator *obxiterator = NULL; ObxList *obxlist = NULL; ObxHeader *obxheader = NULL; ObxHeader *bodyheader = NULL; void *bytebuffer = NULL; int dataLength = 0; OBXDBGFLOW(("ObxGetRecv() entry, handle=0x%08x\trequest=0x%08x\tresponseOut=0x%08x\n", handle, request, responseOut)); if (!request) return OBX_RC_ERR_INAPPROPRIATE; if (request->cmd != OBEX_CMD_GET) return OBX_RC_ERR_INAPPROPRIATE; if (!(response = iobxObjectNew())) { OBXDBGERR(("[ERROR] ObxGetRecv() Error creating response object")); return OBX_RC_ERR_MEMORY; }//We re-write this while loop because the response code of Get command should be 0x90 for continue and 0xA0 for success, not 0x10 for continue and 0x90 for success. /* enter receiving loop */ while ( !done ) { OBXDBGINFO(("ObxGetRecv() Sending GET request..\n")); if ( (rc=iobxObjectSendObject( request, handle )) == OBX_RC_OK ) { if ( (rc=iobxObjectReset( response )) == OBX_RC_OK ) { if ( (rc=iobxObjectRecvObject( response, handle )) == OBX_RC_OK ) {//Response code must have final bit set. if(!(response->cmd & OBEX_CMD_FINAL)) return OBX_RC_ERR_INAPPROPRIATE; switch ( response->cmd & ~OBEX_CMD_FINAL ) { case OBEX_RSP_CONTINUE: OBXDBGINFO(("ObxGetRecv() got OBEX_RSP_CONTINUE from our send attempt.\n")); //----------- /* Special Windows feature .... * Check for Final Flag - if set the object is received complete * Nomally we expect a OBEX_RSP_SUCCESS but ...... */// if (response->cmd & OBEX_CMD_FINAL) {// done = TRUE;// } break; case OBEX_RSP_SUCCESS: // we are done! done = TRUE; OBXDBGINFO(("ObxGetRecv() got response: OBEX_RSP_SUCCESS from our send attempt.\n")); break; default: OBXDBGERR(("[ERROR] ObxGetRecv() *unexpected* response (%02x) from our send attempt.\n", response->cmd)); return OBX_RC_ERR_INAPPROPRIATE;// done = TRUE;// break; } // ok - coalesce headers and request more data //----------- if ( (obxlist=iobxObjectGetHeaderList( response )) ) { if ( (obxiterator=iobxListGetIterator( obxlist )) ) { iobxIteratorReset( obxiterator ); while ( iobxIteratorHasNext( obxiterator ) ) { if ( (obxheader = (ObxHeader *)iobxIteratorNext( obxiterator )) ) { if ( obxheader->identifier == OBEX_HEADER_BODY || obxheader->identifier == OBEX_HEADER_BODY_END ) { /* We may need to bind this data with some data that's already arrived. */ if ( bodyheader ) { /* A header is already in the output request. Append. */ dataLength = iobxBufSize( obxheader->value.byteSequenceValue ); if ( ( bytebuffer=(void *)malloc( dataLength )) ) { OBXDBGBUF(("ObxGetRecv() malloc, addr=0x%08x, len=%d.\n", bytebuffer, dataLength )); if ( iobxBufRead( obxheader->value.byteSequenceValue, bytebuffer, dataLength ) == dataLength) { OBXDBGINFO(("ObxGetRecv() appending body to existing header.\n")); if ( (iobxBufWrite( bodyheader->value.byteSequenceValue, bytebuffer, dataLength )) ) { OBXDBGERR(("[ERROR] ObxGetRecv() Error appending to header.\n")); return OBX_RC_ERR_TRANSPORT; } } else { OBXDBGERR(("[ERROR] ObxGetRecv() not enough data in buffer?.\n")); return OBX_RC_ERR_MEMORY; } free( bytebuffer ); } else { OBXDBGERR(("[ERROR] ObxGetRecv() creating byte buffer.\n")); return OBX_RC_ERR_MEMORY; } /* We don't want to add this one.. since we've combined with an existing one. */ // T.K. we don't free it here, as it gets freed later on. // freeing it now will cause memory coruption. Just set the pointer // to NULL and it gets cleaned up in the end //iobxHeaderFree( obxheader ); obxheader = NULL; } else { /* First one we've seen, so, we'll add it.*/ bodyheader = obxheader; } } /* ** If we haven't coalesced this header we simply add it. ** Note that this could result in duplicate headers from the peer. We make ** no effort to stop them from sending them... we're just a conduit. */ if ( obxheader ) { if ( (rc=iobxObjectAddHeader( responseOut, obxheader, handle )) != OBX_RC_OK ) { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxObjectAddHeader(), rc=%d\n", rc)); return rc; } /* ** Remove this header from the 'request' since 'requestOut' now owns it. ** The itterator will be 'backed up' from the removed item. All ready for ** the next pass through the loop. */ if ( !(iobxListRemove( obxlist, obxiterator )) ) { OBXDBGERR(("[ERROR] ObxGetRecv() Error removing header from response.\n")); return OBX_RC_ERR_TRANSPORT; } } } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxIteratorNext(), rc=%d\n", rc)); return rc; } } // eof while iterator has next /* ** Done with iterator */ iobxIteratorFree( obxiterator ); } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxListGetIterator(), rc=%x\n", rc)); return rc; } } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxObjectGetHeaderList(), rc=%x\n", rc)); return rc; } } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxObjectRecvObject(), rc=%x\n", rc)); done = TRUE; } } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxObjectReset(), rc=%x\n", rc)); done = TRUE; } } else { OBXDBGERR(("[ERROR] ObxGetRecv() bad return code from iobxObjectSendObject(), rc=%x\n", rc)); done = TRUE; } }// responseOut->cmd = OBEX_RSP_SUCCESS | OBEX_CMD_FINAL; return rc;}//**************************************************************OBEX_EXPORT ObxRc ObxTransactionSend( ObxHandle *handle, ObxObject *request, ObxObject *response ) { short done = FALSE; ObxRc rc = OBX_RC_OK; OBXDBGFLOW(("ObxTransactionSend() entry, handle=0x%08x\trequest=0x%08x\tresponse=0x%08x\n", handle, request, response)); if ( request->cmd == OBEX_CMD_GET ) { rc = OBX_RC_ERR_INAPPROPRIATE; } else { while ( !done ) { OBXDBGINFO(("ObxTransactionSend() Sending object...\n")); if ( (rc=iobxObjectSendObject( request, handle )) == OBX_RC_OK ) { if ( response ) { if ( (rc=iobxObjectReset( response )) == OBX_RC_OK ) { if ( (rc=iobxObjectRecvObject( response, handle )) == OBX_RC_OK ) { switch ( response->cmd & ~OBEX_CMD_FINAL ) { /* ** We'll interperate success/continue as ... ok.. send more.. or ok.. we're done. ** Again, the spec states that we should get a 'continue' when dealing with non ** final packets.. but Win32 returns 'success'... we'll treat either as an ** indication to keep going. */ case OBEX_RSP_SUCCESS://When response of SUCCESS has received, this obex command should be terminated. done = TRUE; case OBEX_RSP_CONTINUE: OBXDBGINFO(("ObxTransactionSend() got response: OBEX_RSP_SUCCESS from our send attempt.\n")); if ( request->cmd == OBEX_CMD_CONNECT ) { //handle->maxPacketLen = ntohs( response->meta.connectMeta->max_packet_length ); handle->maxPacketLen = response->meta.connectMeta->max_packet_length; OBXDBGINFO(("ObxTransactionSend() MTU from peer is %d.\n", handle->maxPacketLen)); } /* ** Here's the rub.. a continue could either indicate that the object we have ** needs additional 'sending', (i.e. it wouldn't fit in the MTU) or we're dealing ** with a stream. So... we check to see if the object we're dealing with needs ** to continue to be sent.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -