nuttx-apps/lte/alt1250/usock_handlers/alt1250_sockethdlr.c
SPRESENSE efdbaaefdd lte/alt1250: Fix some bugs in alt1250 daemon
Fix alt1250 daemon to return -ENOTTY when receiving ioctl
request and in the state of using kernel's network stack.
Fix alt1250 daemon to return -ENOTSUP when receiving socket
request and in the state of using kernel's network stack.
Fix alt1250 daemon to set dummy subnet mask in network devices.
This allows the correct network device to be selected when two
network devices exist.
2023-11-09 20:11:07 +08:00

472 lines
16 KiB
C

/****************************************************************************
* apps/lte/alt1250/usock_handlers/alt1250_sockethdlr.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/net/usrsock.h>
#include "alt1250_dbg.h"
#include "alt1250_container.h"
#include "alt1250_socket.h"
#include "alt1250_devif.h"
#include "alt1250_usockevent.h"
#include "alt1250_postproc.h"
#include "alt1250_usrsock_hdlr.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define IS_SUPPORTED_INET_DOMAIN(d) (((d) == AF_INET) || ((d) == AF_INET6))
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
static int postproc_getfl(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_setfl(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* name: send_fctl_command
****************************************************************************/
static int send_fctl_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
FAR struct usock_s *usock,
int32_t cmd,
int32_t val,
FAR int32_t *usock_result)
{
int idx = 0;
FAR void *inparam[3];
/* These members are referenced only when sending a command and
* not when receiving a response, so local variables are used.
*/
inparam[0] = &USOCKET_ALTSOCKID(usock);
inparam[1] = &cmd;
inparam[2] = &val;
USOCKET_SET_RESPONSE(usock, idx++, USOCKET_REP_RESULT(usock));
USOCKET_SET_RESPONSE(usock, idx++, USOCKET_REP_ERRCODE(usock));
set_container_ids(container, USOCKET_USOCKID(usock), LTE_CMDID_FCNTL);
set_container_argument(container, inparam, nitems(inparam));
set_container_response(container, USOCKET_REP_RESPONSE(usock), idx);
set_container_postproc(container, cmd == ALTCOM_SETFL ? postproc_setfl :
cmd == ALTCOM_GETFL ? postproc_getfl : NULL, 0);
return altdevice_send_command(dev->altfd, container, usock_result);
}
/****************************************************************************
* name: postproc_setfl
****************************************************************************/
static int postproc_setfl(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK;
FAR void **resp = CONTAINER_RESPONSE(reply);
/* resp[0]: command return code
* resp[1]: alt1250 errno
*/
dbg_alt1250("%s start\n", __func__);
*usock_xid = USOCKET_XID(usock);
*usock_result = COMBINE_ERRCODE(*(FAR int *)resp[0], *(FAR int *)resp[1]);
if (*usock_result >= 0)
{
USOCKET_SET_STATE(usock, SOCKET_STATE_OPENED);
usocket_commitstate(dev);
switch (USOCKET_REQID(usock))
{
case USRSOCK_REQUEST_SOCKET:
*usock_result = USOCKET_USOCKID(usock);
dbg_alt1250("allocated usockid: %d\n", *usock_result);
break;
/* Below cases are for SOCK_STREAM type socket
* SOCK_STREAM type socket can not be opend on alt1250 side,
* because of LAPI command. It is also using SOCK_STREAM
* type socket to send ioctl() to communicate with daemon.
* So, on BSD-socket spec, aftre socket() API succeeded,
* connect(), bind(), etc, can be called. And on the call,
* socket on alt1250 side should be fixed, therefore,
* open_altsocket() will be called on those cases.
*/
case USRSOCK_REQUEST_CONNECT:
ret = nextstep_connect(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
case USRSOCK_REQUEST_BIND:
ret = nextstep_bind(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
case USRSOCK_REQUEST_LISTEN:
ret = nextstep_listen(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
case USRSOCK_REQUEST_SETSOCKOPT:
ret = nextstep_setsockopt(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
case USRSOCK_REQUEST_GETSOCKOPT:
ret = nextstep_getsockopt(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
case USRSOCK_REQUEST_GETSOCKNAME:
ret = nextstep_getsockname(dev, reply, usock, usock_result,
usock_xid, ackinfo, arg);
break;
default:
dbg_alt1250("unexpected sequence. reqid:0x%02x\n",
USOCKET_REQID(usock));
*usock_result = -EFAULT;
break;
}
}
else
{
USOCKET_SET_STATE(usock, SOCKET_STATE_PREALLOC);
if (USOCKET_TYPE(usock) == SOCK_DGRAM)
{
usocket_free(usock);
}
usocket_commitstate(dev);
}
return ret;
}
/****************************************************************************
* name: postproc_getfl
****************************************************************************/
static int postproc_getfl(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK;
FAR void **resp = CONTAINER_RESPONSE(reply);
/* resp[0]: command return code
* resp[1]: alt1250 errno
*/
dbg_alt1250("%s start\n", __func__);
*usock_xid = USOCKET_XID(usock);
*usock_result = COMBINE_ERRCODE(*(FAR int *)resp[0], *(FAR int *)resp[1]);
if (*usock_result >= 0)
{
/* Set non-blocking flag of socket fd */
*usock_result |= ALTCOM_O_NONBLOCK;
ret = send_fctl_command(dev, reply, usock, ALTCOM_SETFL, *usock_result,
usock_result);
}
if (*usock_result < 0)
{
USOCKET_SET_STATE(usock, SOCKET_STATE_PREALLOC);
if (USOCKET_TYPE(usock) == SOCK_DGRAM)
{
/* In DGRAM case, it is a part of socket() API sequence.
* The socket() API is not returned on application layer.
* So, internal socket should be free here.
*/
usocket_free(usock);
}
usocket_commitstate(dev);
}
return ret;
}
/****************************************************************************
* name: postproc_socket
****************************************************************************/
static int postproc_socket(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK;
FAR void **resp = CONTAINER_RESPONSE(reply);
/* resp[0]: altcom_sockfd
* resp[1]: alt1250 errno
*/
dbg_alt1250("%s start\n", __func__);
*usock_xid = USOCKET_XID(usock);
*usock_result = COMBINE_ERRCODE(*(FAR int *)resp[0], *(FAR int *)resp[1]);
if (*usock_result >= 0)
{
/* In case of success socket allocation */
USOCKET_SET_ALTSOCKID(usock, *usock_result);
ret = send_fctl_command(dev, reply, usock, ALTCOM_GETFL, 0,
usock_result);
}
if (*usock_result < 0)
{
USOCKET_SET_STATE(usock, SOCKET_STATE_PREALLOC);
if (USOCKET_TYPE(usock) == SOCK_DGRAM)
{
/* In DGRAM case, it is a part of socket() API sequence.
* The socket() API is not returned on application layer.
* So, internal socket should be free here.
*/
usocket_free(usock);
}
usocket_commitstate(dev);
}
return ret;
}
/****************************************************************************
* name: send_socket_command
****************************************************************************/
static int send_socket_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
FAR struct usock_s *usock,
int16_t domain,
int16_t type,
int16_t protocol,
FAR int32_t *usock_result)
{
int idx = 0;
FAR void *inparam[3];
/* These members are referenced only when sending a command and
* not when receiving a response, so local variables are used.
*/
inparam[0] = &domain;
inparam[1] = &type;
inparam[2] = &protocol;
USOCKET_SET_RESPONSE(usock, idx++, USOCKET_REP_RESULT(usock));
USOCKET_SET_RESPONSE(usock, idx++, USOCKET_REP_ERRCODE(usock));
set_container_ids(container, USOCKET_USOCKID(usock), LTE_CMDID_SOCKET);
set_container_argument(container, inparam, nitems(inparam));
set_container_response(container, USOCKET_REP_RESPONSE(usock), idx);
set_container_postproc(container, postproc_socket, 0);
return altdevice_send_command(dev->altfd, container, usock_result);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* name: open_altsocket
****************************************************************************/
int open_altsocket(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
FAR struct usock_s *usock,
FAR int32_t *usock_result)
{
int ret;
dbg_alt1250("%s start\n", __func__);
ret = send_socket_command(dev, container, usock,
USOCKET_DOMAIN(usock), USOCKET_TYPE(usock),
USOCKET_PROTOCOL(usock),
usock_result);
if (*usock_result >= 0)
{
USOCKET_SET_STATE(usock, SOCKET_STATE_OPEN);
usocket_commitstate(dev);
}
return ret;
}
/****************************************************************************
* name: usockreq_socket
****************************************************************************/
int usockreq_socket(FAR struct alt1250_s *dev,
FAR struct usrsock_request_buff_s *req,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo)
{
FAR struct usrsock_request_socket_s *request = &req->request.sock_req;
FAR struct usock_s *usock;
FAR struct alt_container_s *container;
int ret = REP_SEND_ACK_WOFREE;
dbg_alt1250("%s start type=%d\n", __func__, request->type);
*usock_xid = request->head.xid;
if (!IS_SUPPORTED_INET_DOMAIN(request->domain))
{
dbg_alt1250("Not support this domain: %u\n", request->domain);
*usock_result = -EAFNOSUPPORT;
return REP_SEND_ACK_WOFREE;
}
else if (!dev->usock_enable && IS_SUPPORTED_INET_DOMAIN(request->domain) &&
request->type != SOCK_CTRL)
{
/* If domain is AF_INET while usock_enable is false,
* set usockid to -ENOTSUP to fallback kernel
* network stack.
*/
*usock_result = -ENOTSUP;
return REP_SEND_ACK_WOFREE;
}
if (!dev->api_enable)
{
dbg_alt1250("Don't allow to call any API now.\n");
*usock_result = -EBUSY;
return REP_SEND_ACK_WOFREE;
}
usock = usocket_alloc(dev, request->type);
if (usock == NULL)
{
dbg_alt1250("socket alloc faild\n");
*usock_result = -EBUSY;
return REP_SEND_ACK_WOFREE;
}
*usock_result = USOCKET_USOCKID(usock);
USOCKET_SET_REQUEST(usock, request->head.reqid, request->head.xid);
USOCKET_SET_SOCKTYPE(usock, request->domain, request->type,
request->protocol);
switch (request->type)
{
case SOCK_STREAM:
case SOCK_CTRL:
dbg_alt1250("allocated usockid: %d\n", *usock_result);
break;
case SOCK_SMS:
ret = alt1250_sms_init(dev, usock, usock_result, ackinfo);
if (*usock_result < 0)
{
usocket_free(usock);
}
break;
case SOCK_DGRAM:
case SOCK_RAW:
dbg_alt1250("allocated usockid: %d\n", *usock_result);
container = container_alloc();
if (container == NULL)
{
dbg_alt1250("no container\n");
usocket_free(usock);
return REP_NO_CONTAINER;
}
ret = open_altsocket(dev, container, usock, usock_result);
if (IS_NEED_CONTAINER_FREE(ret))
{
container_free(container);
}
if (*usock_result < 0)
{
usocket_free(usock);
}
break;
default:
dbg_alt1250("Not support this type: %u\n", request->type);
*usock_result = -EAFNOSUPPORT;
usocket_free(usock);
break;
}
return ret;
}