The handshake callback is intended for embedded SSL systems for debugging support. That is, when a good debugger isn't available and sniffing is impractical. It basically allows a trace of the handshake and won't be helpful for network i/o.
You'll want to use wolfSSL's user I/O callbacks found in cyassl_io.c. By default, wolfSSL uses EmbedReceive() to get data and EmbedSend() to send data. But you can write any I/O functions you want and then register them with CyaSSL_SetIORecv() and CyaSSL_SetIOSend(). You can also set a context for each SSL session with CyaSSL_SetIOReadCtx() and CyaSSL_SetIOWriteCtx(). The void* ctx could point to a structure that has information about where the next read or write buffer is, the size, and anything else you may need to track.
Try to follow the the error handling strategy of the default send/recv functions for maximum compatibility. That is, if wolfSSL calls your Recv function and no data is ready and you don't want to block, just return IO_ERR_WANT_READ. Then when you're notified by your network callback that I/O is ready just call the wolfSSL function again that didn't have data ready, like SSL_read() or SSL_connect() and it will pick up where it left off.