From: Bea L. <bl...@gm...> - 2007-01-17 23:49:08
|
Hi, This is a patch to add support for Put-Delete and Create-Empty operations. The specs define them like this (in 3.3.3.6): "A PUT operation with NO Body or End-of-Body header whatsoever should be treated as a delete request. Similarly, a PUT operation with an empty End-of-Body header request the recipient to create an empty object." Currently it's not possible to recognise Put-Delete and Create-Empty operations on the server side, because Body and End-of-Body data can't be read separately by the programmer (since End-of-Body data is joined with Body data by the library). So if you receive zero body data in a Put operation, you know that it's either a Delete or Create operation, but there's no way to know which one it is. The patch allows for something like this within the user event callback function, in order to distinguish between an ordinary Put request, a Put-Delete and a Create-Empty: case OBEX_EV_REQ: if (obex_cmd == OBEX_CMD_PUT) { int putFlags = OBEX_ObjectGetPutFlags(obj); if ((putFlags & OBEX_FL_PUT_HAS_BODY) == 0) { // no body present in request if ((putFlags & OBEX_FL_PUT_HAS_BODY_END) == 0 ) { // no end-of-body either handleDeleteRequest(); return; } else if ((putFlags & OBEX_FL_PUT_HAS_BODY_END_DATA) == 0 ) { // end of body is empty handleCreateRequest(); return; } } // it's an ordinary put request handlePutRequest(); } Regards, Bea --- obex_const.h.orig 2006-03-08 22:18:55.000000000 +1000 +++ obex_const.h 2006-11-29 17:23:05.000000000 +1000 @@ -104,6 +104,12 @@ #define OBEX_FL_STREAM_DATAEND 0x08 /* Body stream last data */ #define OBEX_FL_SUSPEND 0x10 /* Suspend after sending this header */ +/* For OBEX_ObjectGetPutFlags() */ +#define OBEX_FL_PUT_HAS_BODY 0x01 +#define OBEX_FL_PUT_HAS_BODY_DATA 0x02 +#define OBEX_FL_PUT_HAS_BODY_END 0x04 +#define OBEX_FL_PUT_HAS_BODY_END_DATA 0x08 + /* Transports */ #define OBEX_TRANS_IRDA 1 #define OBEX_TRANS_INET 2 --- obex.h.orig 2006-01-04 09:06:58.000000000 +1000 +++ obex.h 2006-11-29 17:23:10.000000000 +1000 @@ -101,6 +101,8 @@ int OBEX_ObjectSetHdrOffset(obex_object_t *object, unsigned int offset); int OBEX_ObjectReadStream(obex_t *self, obex_object_t *object, const uint8_t **buf); +int OBEX_ObjectGetPutFlags(obex_object_t *object); + int OBEX_UnicodeToChar(uint8_t *c, const uint8_t *uc, int size); int OBEX_CharToUnicode(uint8_t *uc, const uint8_t *c, int size); --- obex.c.orig 2006-05-26 04:09:41.000000000 +1000 +++ obex.c 2006-11-29 17:21:20.000000000 +1000 @@ -725,6 +725,18 @@ return obex_object_readstream(self, object, buf); } +/** + * OBEX_ObjectGetPutFlags - Get the flags for a Put request + * @object: OBEX object + * + * Returns the flags for a Put request. Returns -1 if the command for the + * object is not OBEX_CMD_PUT. + */ +int OBEX_ObjectGetPutFlags(obex_object_t *object) +{ + obex_return_val_if_fail(object != NULL, -1); + return obex_object_getputflags(object); +} /** * OBEX_ObjectSetRsp - Sets the response to a received request. --- obex_object.h.orig 2006-05-04 21:24:21.000000000 +1000 +++ obex_object.h 2006-11-29 17:21:35.000000000 +1000 @@ -82,6 +82,8 @@ unsigned int s_offset; /* Current offset in buf */ int s_stop; /* End of stream */ int s_srv; /* Deliver body as stream when server */ + + int putflags; /* Gives extra info about a received Put request */ } obex_object_t; @@ -101,5 +103,6 @@ int obex_object_readstream(obex_t *self, obex_object_t *object, const uint8_t **buf); int obex_object_suspend(obex_object_t *object); int obex_object_resume(obex_t *self, obex_object_t *object); +int obex_object_getputflags(obex_object_t *object); #endif --- obex_object.c.orig 2006-05-04 21:24:21.000000000 +1000 +++ obex_object.c 2006-11-29 17:21:26.000000000 +1000 @@ -55,6 +55,7 @@ return(NULL); memset(object, 0, sizeof(obex_object_t)); + object->putflags = 0; obex_object_setrsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); return object; } @@ -320,7 +321,7 @@ } if(tx_left < object->s_len) { - /*There is more data left in buffer than tx_left */ + /*There is more data left in buffer than tx_left */ DEBUG(4, "More data than tx_left. Buffer will not be empty\n"); buf_insert_end(txmsg, (uint8_t*) object->s_buf + object->s_offset, tx_left); @@ -801,6 +802,19 @@ len = hlen - 3; if(hi == OBEX_HDR_BODY || hi == OBEX_HDR_BODY_END) { + /* if this is a Put, set some flags */ + if (object->cmd == OBEX_CMD_PUT) { + if (hi == OBEX_HDR_BODY) { + object->putflags |= OBEX_FL_PUT_HAS_BODY; + if (len > 0) + object->putflags |= OBEX_FL_PUT_HAS_BODY_DATA; +} + if (hi == OBEX_HDR_BODY_END) { + object->putflags |= OBEX_FL_PUT_HAS_BODY_END; + if (len > 0) + object->putflags |= OBEX_FL_PUT_HAS_BODY_END_DATA; + } + } /* The body-header need special treatment */ if(object->s_srv) { obex_object_receive_stream(self, hi, source, len); @@ -943,3 +957,10 @@ return 0; } + +int obex_object_getputflags(obex_object_t *object) +{ + if (object->cmd != OBEX_CMD_PUT) + return -1; + return object->putflags; +} |
From: Hendrik S. <po...@he...> - 2007-01-18 00:57:19
|
Am Donnerstag 18 Januar 2007 00:49 schrieb Bea Lam: > This is a patch to add support for Put-Delete and Create-Empty > operations. The specs define them like this (in 3.3.3.6): "A PUT > operation with NO Body or End-of-Body header whatsoever should be > treated as a delete request. Similarly, a PUT operation with an empty > End-of-Body header request the recipient to create an empty object." [...] > } else if ((putFlags & OBEX_FL_PUT_HAS_BODY_END_DATA) == 0 ) { > // end of body is empty > handleCreateRequest(); > return; > } Is that really necessary as special case? An empty EOB header should result in a body of length 0. You create() a file, write() 0 bytes and close() it. This is a normal put, isn't it? Removing any checks about length==0 should let that through. The application author needs no special knowledge, then. Something equal goes for the a DELETE. Handling this in OBEX_EV_REQ is much too late if you use the streaming mechanism. There, you open the file in OBEX_EV_REQCHECK (that's where the other headers appear), so your flag must be present at that time, already. But if you do that, you could use a new OBEX_CMD_DELETE instead and thus avoid any new methods. The start is: OBEX_EV_ACCEPTHINT, OBEX_CMD_CONNECT OBEX_EV_REQHINT, OBEX_CMD_CONNECT OBEX_EV_REQ, OBEX_CMD_CONNECT OBEX_EV_REQDONE, OBEX_CMD_CONNECT OBEX_EV_REQHINT, OBEX_CMD_PUT Here, it is usually followed by: OBEX_EV_REQCHECK, OBEX_CMD_PUT OBEX_EV_PROGRESS, OBEX_CMD_PUT OBEX_EV_STREAMAVAIL, OBEX_CMD_PUT * [...] OBEX_EV_REQ, OBEX_CMD_PUT And finally: OBEX_EV_REQDONE, OBEX_CMD_PUT OBEX_EV_REQHINT, OBEX_CMD_DISCONNECT OBEX_EV_REQ, OBEX_CMD_DISCONNECT OBEX_EV_REQDONE, OBEX_CMD_DISCONNECT You can sneak that in somewhere at the start of the middle part. However, naming the flag to what it means (not what it represents) is usually better, thus OBEX_FL_PUT_DELETE. I would still vote for an OBEX_CMD_DELETE, though, and omitting the OBEX_CMD_PUT, if possible. HS [*]: yes, that actually has no OBEX_CMD_ associated to it but I consider this a bug. |
From: Bea L. <bl...@gm...> - 2007-01-18 05:52:44
|
On 1/18/07, Hendrik Sattler <po...@he...> wrote: > > Is that really necessary as special case? An empty EOB header should result in > a body of length 0. You create() a file, write() 0 bytes and close() it. This > is a normal put, isn't it? > Removing any checks about length==0 should let that through. The application > author needs no special knowledge, then. Yes, an empty EOB header does have a Body of length 0 -- but an omission of the EOB header (i.e. a Delete request) would also result in a body of length 0. So the flags check is to distinguish between a Delete and a Create (i.e. between having a length==0 and having no data at all). Or, maybe what you mean is that you only need to figure out if it's a Delete, and you don't need to worry about distinguishing between a Create and a normal Put. I'd agree with that -- I only make this distinction because the specs specifically define a "Create" operation as opposed to an ordinary Put operation. But yeah, it doesn't seem particularly useful for an actual application. > Something equal goes for the a DELETE. Handling this in OBEX_EV_REQ is much > too late if you use the streaming mechanism. There, you open the file in > OBEX_EV_REQCHECK (that's where the other headers appear), so your flag must > be present at that time, already. > But if you do that, you could use a new OBEX_CMD_DELETE instead and thus avoid > any new methods. I totally agree that it's very late to check for a DELETE in the OBEX_EV_REQCHECK, and it would be great to have a new command OBEX_CMD_DELETE. However, the problem is that there is no way of knowing that a Put operation is actually a "Delete" operation until the request header data has been processed (i.e. you have determined there are no Body or EOB headers). So, when a server receives a Delete request, it will immediately see the PUT command and pass OBEX_CMD_PUT to the programmer as the command for the REQHINT event. It can then process the header data and determine that it is actually a Delete, but it seems strange for the server to pass OBEX_CMD_PUT as the command for the initial OBEX_EV_REQHINT and then change to passing an OBEX_CMD_PUT for the later OBEX_EV_REQCHECK and OBEX_EV_REQ events. Also, if the client takes more than one packet to send all its headers, the server cannot tell whether it is a Delete operation until all request packets have been received (i.e. until OBEX_EV_REQ) and it can determine that no Body or EOB headers have been received. > naming the flag to what it means (not what it represents) is usually better, > thus OBEX_FL_PUT_DELETE. I would still vote for an OBEX_CMD_DELETE, though, > and omitting the OBEX_CMD_PUT, if possible. > That's true, a OBEX_FL_PUT_DELETE flag would be better, since the programmer's probably more interested in the fact that there's a Delete operation than the fact that particular headers are empty or missing. I was assuming that this information might be useful during the middle packets (when it hasn't been determined whether it's a delete operation) but it's probably not that useful to the programmer, really. So, what if the patch allows for something like this instead, in the user event callback function? case OBEX_EV_REQ: if (obex_cmd == OBEX_CMD_PUT) { int putFlags = OBEX_ObjectGetPutFlags(obj); if (putFlags & OBEX_FL_PUT_DELETE) { // it's a delete } else { // it's an ordinary put request, or a "create" if no body data has been received } } Perhaps OBEX_ObjectGetPutFlags() should be OBEX_ObjectGetRequestFlags() instead, so that it's more generic in case other request flags are added in the future. Regards, Bea |
From: Bea L. <bl...@gm...> - 2007-01-23 23:34:20
|
Hi Hendrik, I've looked at it again and I've realised it's possible to recognise the Delete and Create commands without a patch. To work around it, the user just has to keep track of whether the OBEX_EV_STREAMAVAIL event is received or not in order to determine whether the command is a Put-Delete, since this event is not received if no Body nor End-of-Body headers are received while streaming a Put. To recognise a Create command, the user needs to recognise Delete commands; i.e. if it's a Put operation that's not a Delete, and the body length is zero, it must be a Create. So with this workaround, the Create command cannot be recognised without also recognising the Delete command. Thanks for going through the patch. Regards, Bea |
From: Johan H. <joh...@no...> - 2007-01-24 19:24:45
|
Hi Bea, On Wed, Jan 24, 2007, Bea Lam wrote: > I've looked at it again and I've realised it's possible to recognise > the Delete and Create commands without a patch. To work around it, the > user just has to keep track of whether the OBEX_EV_STREAMAVAIL event > is received or not in order to determine whether the command is a > Put-Delete, since this event is not received if no Body nor > End-of-Body headers are received while streaming a Put. > > To recognise a Create command, the user needs to recognise Delete > commands; i.e. if it's a Put operation that's not a Delete, and the > body length is zero, it must be a Create. So with this workaround, the > Create command cannot be recognised without also recognising the > Delete command. It seems that even if detecting these cases is currently possible, a simpler (and more intuitive) way to do it would be a good thing to have. A "get flags" function would probably do the trick. Is the patch you sent still your latest proposal or do you have an updated version? (I don't really have any strong opinion about whether it should be OBEX_ObjectGetPutFlags or a generic OBEX_ObjectGetRequestFlags). Johan |
From: Bea L. <bl...@gm...> - 2007-01-25 02:01:48
|
Hi Johan, Yes, it would definitely be much easier to ask the library instead of working it out yourself. I do have an updated patch that I have included below. It will return the appropriate flags for Put-Delete and Create-Empty operations. (I don't really see the point of the Create operation, but I have included it since it's defined in the spec, and anyway it would be odd to have only one possible flag.) Unfortunately the OBEX_ObjectGetPutFlags() will return the "wrong" value if called before the body headers are processed (e.g. in the OBEX_EV_REQHINT), but since that's how the operations are defined in the spec, there's not much that can be done about it. The programmer will just have to deal with the possibility that when you get a Put command at the OBEX_EV_REQHINT, it might actually turn out to be a Delete at the OBEX_EV_REQ. So with the updated patch you could do this in the event callback: case OBEX_EV_REQ: if (obex_cmd == OBEX_CMD_PUT) { int putFlags = OBEX_ObjectGetPutFlags(object); if (putFlags & OBEX_FL_PUT_DELETE) { handleDeleteRequest(); } else if (putFlags & OBEX_FL_PUT_CREATE) { handleCreateRequest(); } else { handleOrdinaryPutRequest(); } } } Except the create could be handled the same way as an ordinary Put anyway. Also you could subsitute "&" for "==" since it can't be a Create and a Delete at the same time. Here is the patch: --- lib/obex.c.orig 2006-05-26 04:09:41.000000000 +1000 +++ lib/obex.c 2007-01-25 11:37:10.000000000 +1000 @@ -725,6 +725,25 @@ return obex_object_readstream(self, object, buf); } +/** + * OBEX_ObjectGetPutFlags - Get the flags for a received Put request + * @object: OBEX object + * + * Returns the flags for a received Put request to indicate whether the request + * is for a special "Delete" or "Create" operation. + * + * Note! A Put request cannot be determined to be a "Delete" or "Create" operation + * until the appropriate headers have been received and read, so this function + * effectively returns the wrong value if it is called before the request is + * fully processed (i.e. before the OBEX_EV_REQ event). + * + * Returns 0 if the command for the object is not OBEX_CMD_PUT. + */ +int OBEX_ObjectGetPutFlags(obex_object_t *object) +{ + obex_return_val_if_fail(object != NULL, -1); + return obex_object_getputflags(object); +} /** * OBEX_ObjectSetRsp - Sets the response to a received request. --- lib/obex_object.c.orig 2006-05-04 21:24:21.000000000 +1000 +++ lib/obex_object.c 2007-01-25 11:18:59.000000000 +1000 @@ -55,6 +55,9 @@ return(NULL); memset(object, 0, sizeof(obex_object_t)); + object->body_received = 0; + object->bodyend_received = 0; + object->bodyend_received_empty = 0; obex_object_setrsp(object, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); return object; } @@ -320,7 +323,7 @@ } if(tx_left < object->s_len) { - /*There is more data left in buffer than tx_left */ + /*There is more data left in buffer than tx_left */ DEBUG(4, "More data than tx_left. Buffer will not be empty\n"); buf_insert_end(txmsg, (uint8_t*) object->s_buf + object->s_offset, tx_left); @@ -801,6 +804,16 @@ len = hlen - 3; if(hi == OBEX_HDR_BODY || hi == OBEX_HDR_BODY_END) { + /* if this is a Put, set some flags */ + if (object->cmd == OBEX_CMD_PUT) { + if (hi == OBEX_HDR_BODY) { + object->body_received = 1; + } else { /* OBEX_HDR_BODY_END */ + object->bodyend_received = 1; + if (len == 0) + object->bodyend_received_empty = 1; + } + } /* The body-header need special treatment */ if(object->s_srv) { obex_object_receive_stream(self, hi, source, len); @@ -943,3 +956,22 @@ return 0; } + +int obex_object_getputflags(obex_object_t *object) +{ + if (object->cmd != OBEX_CMD_PUT) + return 0; + + /* A Put-Delete has no body nor end-of-body, and a Create-Empty has no + body and an empty end-of-body (spec 3.3.3.6) */ + if (!object->body_received) { + if (!object->bodyend_received) { + return OBEX_FL_PUT_DELETE; + } else { + if (object->bodyend_received_empty) + return OBEX_FL_PUT_CREATE; + } + } + + return 0; +} --- lib/obex_object.h.orig 2006-05-04 21:24:21.000000000 +1000 +++ lib/obex_object.h 2007-01-25 11:19:03.000000000 +1000 @@ -82,6 +82,10 @@ unsigned int s_offset; /* Current offset in buf */ int s_stop; /* End of stream */ int s_srv; /* Deliver body as stream when server */ + + int body_received; /* a body header was found in received headers */ + int bodyend_received; /* an end-of-body header was found in received headers */ + int bodyend_received_empty; /* received an end-of-body header and it was empty */ } obex_object_t; @@ -102,4 +106,6 @@ int obex_object_suspend(obex_object_t *object); int obex_object_resume(obex_t *self, obex_object_t *object); +int obex_object_getputflags(obex_object_t *object); + #endif --- include/obex.h.orig 2006-01-04 09:06:58.000000000 +1000 +++ include/obex.h 2007-01-25 11:19:26.000000000 +1000 @@ -100,6 +100,7 @@ int OBEX_ObjectSetNonHdrData(obex_object_t *object, const uint8_t *buffer, unsigned int len); int OBEX_ObjectSetHdrOffset(obex_object_t *object, unsigned int offset); int OBEX_ObjectReadStream(obex_t *self, obex_object_t *object, const uint8_t **buf); +int OBEX_ObjectGetPutFlags(obex_object_t *object); int OBEX_UnicodeToChar(uint8_t *c, const uint8_t *uc, int size); int OBEX_CharToUnicode(uint8_t *uc, const uint8_t *c, int size); --- include/obex_const.h.orig 2006-03-08 22:18:55.000000000 +1000 +++ include/obex_const.h 2007-01-25 11:19:30.000000000 +1000 @@ -104,6 +104,10 @@ #define OBEX_FL_STREAM_DATAEND 0x08 /* Body stream last data */ #define OBEX_FL_SUSPEND 0x10 /* Suspend after sending this header */ +/* For OBEX_ObjectGetPutFlags() */ +#define OBEX_FL_PUT_DELETE 0x01 /* The received Put request is for a Put-Delete */ +#define OBEX_FL_PUT_CREATE 0x02 /* The received Put request is for a Create-Empty */ + /* Transports */ #define OBEX_TRANS_IRDA 1 #define OBEX_TRANS_INET 2 Regards, Bea On 1/25/07, Johan Hedberg <joh...@no...> wrote: > Hi Bea, > > On Wed, Jan 24, 2007, Bea Lam wrote: > > I've looked at it again and I've realised it's possible to recognise > > the Delete and Create commands without a patch. To work around it, the > > user just has to keep track of whether the OBEX_EV_STREAMAVAIL event > > is received or not in order to determine whether the command is a > > Put-Delete, since this event is not received if no Body nor > > End-of-Body headers are received while streaming a Put. > > > > To recognise a Create command, the user needs to recognise Delete > > commands; i.e. if it's a Put operation that's not a Delete, and the > > body length is zero, it must be a Create. So with this workaround, the > > Create command cannot be recognised without also recognising the > > Delete command. > > It seems that even if detecting these cases is currently possible, a > simpler (and more intuitive) way to do it would be a good thing to have. > A "get flags" function would probably do the trick. Is the patch you > sent still your latest proposal or do you have an updated version? (I > don't really have any strong opinion about whether it should be > OBEX_ObjectGetPutFlags or a generic OBEX_ObjectGetRequestFlags). > > Johan > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > Openobex-users mailing list > Ope...@li... > http://lists.sourceforge.net/lists/listinfo/openobex-users > |
From: Marcel H. <ma...@ho...> - 2007-01-25 08:41:48
|
Hi Bea, > Yes, it would definitely be much easier to ask the library instead of > working it out yourself. I do have an updated patch that I have > included below. It will return the appropriate flags for Put-Delete > and Create-Empty operations. (I don't really see the point of the > Create operation, but I have included it since it's defined in the > spec, and anyway it would be odd to have only one possible flag.) > > Unfortunately the OBEX_ObjectGetPutFlags() will return the "wrong" > value if called before the body headers are processed (e.g. in the > OBEX_EV_REQHINT), but since that's how the operations are defined in > the spec, there's not much that can be done about it. The programmer > will just have to deal with the possibility that when you get a Put > command at the OBEX_EV_REQHINT, it might actually turn out to be a > Delete at the OBEX_EV_REQ. I am fine with an API extension. Please work out the best patch and have Hendrik and Johan agree on it. Regards Marcel |
From: Bea L. <bl...@gm...> - 2007-01-28 23:54:14
Attachments:
putspecial.patch
|
Hi, Thanks Marcel, I think the patch I included earlier works well, as programmers can easily work out whether an OBEX_CMD_PUT means a special Delete or Create operation. But I would appreciate any suggestions for improving it. Would the maintainers consider this patch, or point out any problems with it that stop it from being applied? I have included it again here as an attachment. thanks, Bea On 1/25/07, Marcel Holtmann <ma...@ho...> wrote: > Hi Bea, > > > Yes, it would definitely be much easier to ask the library instead of > > working it out yourself. I do have an updated patch that I have > > included below. It will return the appropriate flags for Put-Delete > > and Create-Empty operations. (I don't really see the point of the > > Create operation, but I have included it since it's defined in the > > spec, and anyway it would be odd to have only one possible flag.) > > > > Unfortunately the OBEX_ObjectGetPutFlags() will return the "wrong" > > value if called before the body headers are processed (e.g. in the > > OBEX_EV_REQHINT), but since that's how the operations are defined in > > the spec, there's not much that can be done about it. The programmer > > will just have to deal with the possibility that when you get a Put > > command at the OBEX_EV_REQHINT, it might actually turn out to be a > > Delete at the OBEX_EV_REQ. > > I am fine with an API extension. Please work out the best patch and have > Hendrik and Johan agree on it. > > Regards > > Marcel > > > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > Openobex-users mailing list > Ope...@li... > http://lists.sourceforge.net/lists/listinfo/openobex-users > |