text: /*
   * 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.
   */
  #ifndef __SYS_MN_SOCKET_H_
  #define __SYS_MN_SOCKET_H_
  
  #include <inttypes.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /*
   * Address/protocol family.
   */
  #define MN_AF_INET              4
  #define MN_PF_INET              MN_AF_INET
  #define MN_AF_INET6             6
  #define MN_PF_INET6             MN_AF_INET6
  
  /*
   * Socket types
   */
  #define MN_SOCK_STREAM          1
  #define MN_SOCK_DGRAM           2
  
  /*
   * Protocol
   */
  #define MN_PROTO_UDP            17
  #define MN_PROTO_TCP            6
  
  /*
   * Error codes from mn_socket interface.
   */
  #define MN_EAFNOSUPPORT         1
  #define MN_EPROTONOSUPPORT      2
  #define MN_ENOBUFS              3
  #define MN_EINVAL               4
  #define MN_ENOTCONN             5
  #define MN_ECONNABORTED         6
  #define MN_EDESTADDRREQ         7
  #define MN_EADDRINUSE           8
  #define MN_ETIMEDOUT            9
  #define MN_EAGAIN               10
  #define MN_EUNKNOWN             11
  #define MN_EADDRNOTAVAIL        12
  #define MN_ENETUNREACH          13
  #define MN_OPNOSUPPORT          14
  
  /*
   * Multicast macros
   */
  #define MN_IN_MULTICAST(a)                                              \
      ((((uint32_t)(a)) & 0xf0000000) == 0xe0000000)
  
  #define MN_IN6_IS_ADDR_MULTICAST(a)                                     \
      ((a)->s_addr[0] == 0xff)
  
  struct mn_socket;
  struct mn_socket_ops;
  struct mn_sock_cb;
  struct os_mbuf;
  
  struct mn_socket {
      const union mn_socket_cb *ms_cbs;          /* filled in by user */
      void *ms_cb_arg;                           /* filled in by user */
      const struct mn_socket_ops *ms_ops;        /* filled in by mn_socket */
  };
  
  /*
   * Callbacks. Socket callbacks are for sockets which exchange
   * data. Listen callback is for TCP listen sockets.
   */
  union mn_socket_cb {
      struct {
          void (*readable)(void *cb_arg, int err);
          void (*writable)(void *cb_arg, int err);
      } socket;
      struct {
          int (*newconn)(void *cb_arg, struct mn_socket *new);
      } listen;
  };
  
  struct mn_sockaddr {
      uint8_t msa_len;
      uint8_t msa_family;
      char    msa_data[2];
  };
  
  struct mn_in_addr {
      uint32_t s_addr;
  };
  
  struct mn_sockaddr_in {
      uint8_t msin_len;
      uint8_t msin_family;
      uint16_t msin_port;
      struct mn_in_addr msin_addr;
  };
  
  struct mn_in6_addr {
      uint8_t s_addr[16];
  };
  
  struct mn_sockaddr_in6 {
      uint8_t msin6_len;
      uint8_t msin6_family;
      uint16_t msin6_port;
      uint32_t msin6_flowinfo;
      struct mn_in6_addr msin6_addr;
      uint32_t msin6_scope_id;
  };
  
  extern const uint32_t nm_in6addr_any[4];
  
  /*
   * Structure for multicast join/leave
   */
  struct mn_mreq {
      uint8_t mm_idx;			/* interface index; must not be 0 */
      uint8_t mm_family;			/* address family */
      union {
          struct mn_in_addr v4;
          struct mn_in6_addr v6;
      } mm_addr;
  };
  
  #define MN_SO_LEVEL                     0xfe
  
  #define MN_MCAST_JOIN_GROUP             1
  #define MN_MCAST_LEAVE_GROUP            2
  #define MN_MCAST_IF                     3
  #define MN_REUSEADDR                    4
  
  /*
   * Socket calls.
   *
   * mn_connect() for TCP is asynchronous. Once connection has been established,
   * socket callback (*writable) will be called.
   *
   * mn_sendto() is asynchronous as well. If it fails due to buffer shortage,
   * socket provider should call (*writable) when more data can be sent.
   *
   * mn_recvfrom() returns immediatelly if no data is available. If data arrives,
   * the callback (*readable) will be called. Once that happens, owner of the
   * socket should keep calling mn_recvfrom() until it has drained all the
   * data from the socket.
   *
   * If remote end closes the socket, socket callback (*readable) will be
   * called.
   */
  int mn_socket(struct mn_socket **, uint8_t domain, uint8_t type, uint8_t proto);
  int mn_bind(struct mn_socket *, struct mn_sockaddr *);
  int mn_connect(struct mn_socket *, struct mn_sockaddr *);
  int mn_listen(struct mn_socket *, uint8_t qlen);
  
  int mn_recvfrom(struct mn_socket *, struct os_mbuf **,
    struct mn_sockaddr *from);
  int mn_sendto(struct mn_socket *, struct os_mbuf *, struct mn_sockaddr *to);
  
  int mn_getsockopt(struct mn_socket *, uint8_t level, uint8_t optname,
    void *optval);
  int mn_setsockopt(struct mn_socket *, uint8_t level, uint8_t optname,
    void *optval);
  
  int mn_getsockname(struct mn_socket *, struct mn_sockaddr *);
  int mn_getpeername(struct mn_socket *, struct mn_sockaddr *);
  
  int mn_close(struct mn_socket *);
  
  #define mn_socket_set_cbs(sock, cb_arg, cbs)                            \
      do {                                                                \
          (sock)->ms_cbs = (cbs);                                         \
          (sock)->ms_cb_arg = (cb_arg);                                   \
      } while (0)
  
  /*
   * Address conversion
   */
  
  #define MN_INET_ADDRSTRLEN  16
  #define MN_INET6_ADDRSTRLEN 46
  
  int mn_inet_pton(int af, const char *src, void *dst);
  const char *mn_inet_ntop(int af, const void *src, void *dst, int len);
  
  /*
   * Info about interfaces.
   */
  #define MN_ITF_NAME_MAX    8
  
  /*
   * Interface flags
   */
  #define MN_ITF_F_UP        1
  #define MN_ITF_F_MULTICAST 2
  #define MN_ITF_F_LINK      4
  
  struct mn_itf {
      char mif_name[MN_ITF_NAME_MAX];
      uint8_t mif_idx;
      uint8_t mif_flags;
  };
  
  struct mn_itf_addr {
      uint8_t mifa_family;
      uint8_t mifa_plen;
      union {
          struct mn_in_addr v4;
          struct mn_in6_addr v6;
      } mifa_addr;
  };
  
  /*
   * Iterate through interfaces, and their addresses
   */
  int mn_itf_getnext(struct mn_itf *);
  int mn_itf_addr_getnext(struct mn_itf *, struct mn_itf_addr *);
  
  /*
   * Find specific interface, given name.
   */
  int mn_itf_get(char *name, struct mn_itf *mi);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* __SYS_MN_SOCKET_H_ */
  