New subfunctions for sendmsg(), recvmsg(), setsockopt() and getsockopt() are provided for this functionality.
To achieve this, the following structures are required in the header file sys.socket.h:
/* * struct instead of cmsghdr in case of Handoff-Handling */ struct red_info_tcp { short fd; /* file descriptor (listener) */ short port; /* port number */ short domain; /* address family */ short flags; /* flags of success */ int cid; /* cid */ int if_index; /* interface index listener process */ int rwindow; /* max read window */ int wwindow; /* max write window */ }; struct red_info_iso { short fd; /* file descriptor (listener) */ short domain; /* address family */ short flags; /* flags of success */ short tsellen; /* length of TSEL */ int rwindow; /* max read window */ int wwindow; /* max write window */ char tsel[32]; /* TSEL application */ char tesn[8]; /* TESN hostname */ }; struct red_info_svrs { short domain; /* domain (server[accept]) */ short fd_server; /* file descriptor(server[accept]) */ int tsor_server; /* tsap_open_reference 1. server_socket */ int cref_server; /* cref server[accept]_socket */ }; struct cmsg_redhdr { u_int cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type of operation */ union { char tsap_name[TSAPNAMMAXLEN]; /* needed tsap_name for shared tsap */ struct red_info_iso red_liso; /* needed tsap_name for iso shared tsap */ struct red_info_tcp red_ltcp; /* Info of listen socket */ struct red_info_tcp red_ctcp; /* Info of client */ struct red_info_svrs red_svrs; /* Info of server socket ("accept") */ } cmsg_redhdr_info; short bind_ok; /* open shared TSAP successfull */ short handoff_ok; /* handoff successfull */ short tsap_name_len; /* length of tsap_name */ short fd_server; /* file descriptor redirected socket */ short domain; /* address family */ int tsn; /* tsn server-process */ #define redhdr_tsap_name cmsg_redhdr_info.tsap_name #define redhdr_red_liso cmsg_redhdr_info.red_liso #define redhdr_red_ltcp cmsg_redhdr_info.red_ltcp #define redhdr_red_ctcp cmsg_redhdr_info.red_ctcp #define redhdr_red_svrs cmsg_redhdr_info.red_svrs };
Execution sequence
Acceptance: client = C, listener = L, server = S
The listen socket of listener L has the file descriptor fd = 1.
A connection under the AF_ISO domain is established between listener L and server S usingfd 0 on the listener side and fd 0 on the server side. This connection can be established either in blocking mode or in non-blocking mode.
In non-blocking mode, it is mandatory for pending events to be polled using select() or soc_poll().
The AF_ISO listen socket on the server side has the fd 0. The endpoint is moved in the following stages:
C establishes a connection to L.
The connection is accepted by L and moved to S.
In L, sendmsg() is used to forward to S information on the domain of the connection established by C and the fd of the accept socket for this connection over the local AF_ISO connection.
int sendmsg(int s, struct msghdr * msg, int flags);
msg.msg_control is a pointer to a structure of the type cmsg_redhdr.
The length of struct cmsg_redhdr is entered in msg.msg_control_len.
cmsg_redhdr.cmsg_len = sizeof(cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_DATAThe address family of the endpoint to be moved must be entered in cmsg_redhdr.domain and depending on this address family, the fd of the accept socket must be entered in cmsg_redhdr.redhdr_red_liso (for AF_ISO) or cmsg_redhdr.redhdr_red_ltcp (for AF_INET or AF_INET6) in the element fd.
The S side reads from the AF_ISO connection using recvmsg().
int recvmsg(int s, struct msghdr * msg, int flags);
msg.msg_control is a pointer to a structure of the type cmsg_redhdr.
cmsg_redhdr.cmsg_len = sizeof(cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_DATAAction on S:
On the basis of the information from L contained in the structure of the type cmsg_redhdr that has been passed, a new connection endpoint is generated using an internal bind().
The fd of this endpoint is returned in cmsg_redhdr.fd_server together with the address family in cmsg_redhdr.domain.The S side passes the information that the new connection endpoint has been created to the L side.
int sendmsg(int s, struct msghdr * msg, int flags);
msg.msg_control is a pointer to a structure of the type cmgs_redhdr.
cmsg_redhdr.cmsg_ len = sizeof(cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_BDOKThe address family of the socket for the new endpoint must additionally be entered in cmsg_redhdr.domain and the fd of this socket must be entered in cmsg_redhdr.fd_server.
The L side must wait for the information that the new endpoint is available before the end point can actually be moved.
int recvmsg(int s, struct msghdr * msg, int flags);
msg.msg_control is a pointer to a structure of the type cmsg_redhdr.
cmsg_redhdr.cmsg.len = sizeof(struct cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_BDOKThe address family of the endpoint to be moved must additionally be entered in cmsg_redhdr.domain and depending on this address family, the fd of the accept socket must be entered in cmsg_redhdr.redhdr_red_liso (for AF_ISO) or cmsg_redhdr.redhdr_red_ltcp (for AF_INET or AF_INET6) in the element fd.
The cmsg_redhdr.bind_ok field can be used to check whether successful creation of the new endpoint on the S side has been acknowledged with REDBIND_OK.
A data stop is then triggered internally for this connection endpoint. This means that data can be sent from the client, but it is no longer delivered to the old connection end point.
setsockopt() is then issued on the L side to move the functionality of the endpoint. This means that the partner information entered in the accept socket is transferred to the socket of the new end point in the server.
int setsockopt(int s, int level, int optname, char * optval, int optlen);
optval is a pointer to a structure of the type cmsg_redhdr.
level = SOL_TRANSPORT
optname = TPOPT_REDI_CALLcmsg_redhdr.cmsg_len = sizeof(struct cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_CALLgetsockopt()is issued on the S side to wait for data from the accept socket on the L side.
int getsockopt(int s, int level, int optname, char * optval, int* optlen);
optval is a pointer to a structure of the type cmsg_redhdr.
level = SOL_TRANSPORT
optname = TPOPT_REDI_CALLcmsg_redhdr.cmsg_len = sizeof(struct cmsg_redhdr)
cmsg_redhdr.cmsg_level = SOL_TRANSPORT
cmsg_redhdr.cmsg_type = TPOPT_REDI_CALLThe address family must be entered in cmsg_redhdr.domain and the fd of the socket for the new endpoint must be entered in cmsg_redhdr.fd_server.
Once the event has been received and picked up, the connection environment is finally established and the data stop for the connection is canceled. This means that data is now delivered to the new connection endpoint.
The accept socket of the original endpoint can now be closed with soc_close(), as can the AF_ISO connection for handoff communication.