-
• #2
It's exactly like the situation with
connect
. If it makes more sense, think of the description as:Start to send
len
bytes frombuf
on socket numbersckt
. Return the number of bytes that have been accepted, 0 if busy, or -1 if there was an errorThis is pretty much what happens on an OS anyway, it's not like the computer sends that packet over the network and then returns - it goes into a buffer (and it doesn't expect that the buffer you passed to
send
hangs around).And yes, the data is lost afterwards as the array is stored on the stack - if the ESP8266's send function needs the data to stay around, you'll have to allocate your own buffer for it.
It's worth looking at socketserver.c though - it should be pretty obvious how
net->
functions get used in there. -
• #3
@Gordon
As always ... awesome answers. Based on what you've said, I think I can make some tests tonight. The answers for connect() were perfect.In a lot of your answers, you have invited me to go look at code ... and being pointed to the correct code is GREAT ... however ... when you say something should be obvious, you are over assuming my skills. I have and can lay my hands on ESP8266 skills as needed but Espruino internals are a "grind". That is definitely NOT to say that they are poor in any way ... just a lot of stuff that I think is all locked in your head. Without your responses on the forum, this port would be dead or dramatically further back than where it is.
Neil
When implementing a new network component for a new board (eg. ESP8266), we have to create a function that is mapped to the JsNetwork
send
function. This is a function with the following signature:int send(struct JsNetwork *net, int sckt, const void *buf, size_t len)
What I feel I need to know are the semantics and contract for this function.
What I sense is that, in its simplest mode, it is supposed to send
len
bytes of data starting at the memory pointer supplied bybuf
through the socket identified bysckt
. It should return the number of bytes actually sent, 0 if no bytes were sent and -1 if there was an error.Unfortunately for some devices such as the ESP8266, this semantics needs further consideration. In the ESP8266 the correspond function to transmit data is called
espconn_send
. However, since nothing in ESP8266 is blocking, this call takes a buffer of data and then will eventually transmit it. When the transmission has completed, a registered call-back function is invoked to let us know that the data has been sent.Now ... let us try and map this to the apparent Espruino architecture. A naive implementation of the Espruino
send()
would be to simply callespconn_send()
however what should we then return? If we return the length of data thatsend()
was provided, then we are semantically declaring that all the data was transmitted which isn't the case. In fact, it appears that immediately following a successfulsend()
using HTTP, we then close the socket.The next possible design thought is that when
send()
is called, we do invokeespconn_send()
but return 0 ... indicating that NO data has been transmitted. The assumption here is thatsend()
will continue to be invoked over and over. The ESP8266 layer could be watching for the previous send to complete and, when it does, we return that the data was sent. This may work, but makes a broad assumption. It assumes that whensend()
is called with some data and gets a return of 0 ... it will continually call with the SAME data to be sent over and over again ... it isn't clear in the semantics if this is correct or not.Another open question is the buffer passed into the
send()
call. Should the content be copied from the request or can we assume that the memory pointer is "good" and "stable" until the data has actually been transmitted at some time in the future. If we can't assume that, then we have the unfortunate circumstance of having to duplicate the memory buffer to hold a copy while we transmit.As we see ... we are starting to ask complex semantic questions which weren't immediately obvious from such an innocuous looking function such as
send()
.Neil