aboutsummaryrefslogtreecommitdiff
path: root/src/core/socket.h
blob: 6a608d0a928a3b8046cc2402080514be3cc0e3ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//
// Copyright 2017 Garrett D'Amore <garrett@damore.org>
//
// This software is supplied under the terms of the MIT License, a
// copy of which should be located in the distribution where this
// file was obtained (LICENSE.txt).  A copy of the license may also be
// found online at https://opensource.org/licenses/MIT.
//

#ifndef CORE_SOCKET_H
#define CORE_SOCKET_H


// NB: This structure is supplied here for use by the CORE. Use of this library
// OUSIDE of the core is STRICTLY VERBOTEN.  NO DIRECT ACCESS BY PROTOCOLS OR
// TRANSPORTS.
struct nni_socket {
	nni_mtx			s_mx;
	nni_cv			s_cv;

	uint32_t		s_id;
	uint32_t		s_refcnt;
	nni_cv			s_refcv;

	nni_msgq *		s_uwq;  // Upper write queue
	nni_msgq *		s_urq;  // Upper read queue

	uint16_t		s_protocol;
	uint16_t		s_peer;
	uint32_t		s_flags;

	nni_proto_pipe_ops	s_pipe_ops;
	nni_proto_sock_ops	s_sock_ops;

	void *			s_data; // Protocol private

	// XXX: options
	nni_duration		s_linger;       // linger time
	nni_duration		s_sndtimeo;     // send timeout
	nni_duration		s_rcvtimeo;     // receive timeout
	nni_duration		s_reconn;       // reconnect time
	nni_duration		s_reconnmax;    // max reconnect time

	nni_list		s_eps;          // active endpoints
	nni_list		s_pipes;        // ready pipes (started)
	nni_list		s_idles;        // idle pipes (not ready)
	nni_list		s_events;       // pending events
	nni_list		s_notify;       // event watchers
	nni_cv			s_notify_cv;    // wakes notify thread
	nni_mtx			s_notify_mx;    // protects s_notify list

	size_t			s_rcvmaxsz;     // maximum receive size

	nni_thr			s_notifier;

	int			s_ep_pend;      // EP dial/listen in progress
	int			s_closing;      // Socket is closing
	int			s_closed;       // Socket closed
	int			s_besteffort;   // Best effort mode delivery
	int			s_senderr;      // Protocol state machine use
	int			s_recverr;      // Protocol state machine use

	nni_event		s_recv_ev;      // Event for readability
	nni_event		s_send_ev;      // Event for sendability

	nni_notifyfd		s_send_fd;
	nni_notifyfd		s_recv_fd;

	uint32_t		s_nextid;       // Next Pipe ID.
};

extern int nni_sock_hold(nni_sock **, uint32_t);
extern int nni_sock_hold_close(nni_sock **, uint32_t);
extern void nni_sock_held_close(nni_sock *);
extern void nni_sock_rele(nni_sock *);
extern int nni_sock_open(nni_sock **, uint16_t);
extern void nni_sock_close(nni_sock *);
extern int nni_sock_shutdown(nni_sock *);
extern uint16_t nni_sock_proto(nni_sock *);
extern uint16_t nni_sock_peer(nni_sock *);
extern int nni_sock_setopt(nni_sock *, int, const void *, size_t);
extern int nni_sock_getopt(nni_sock *, int, void *, size_t *);
extern int nni_sock_recvmsg(nni_sock *, nni_msg **, nni_time);
extern int nni_sock_sendmsg(nni_sock *, nni_msg *, nni_time);
extern int nni_sock_dial(nni_sock *, const char *, nni_ep **, int);
extern int nni_sock_listen(nni_sock *, const char *, nni_ep **, int);
extern uint32_t nni_sock_id(nni_sock *);

extern void nni_sock_lock(nni_sock *);
extern void nni_sock_unlock(nni_sock *);

// nni_sock_pipe_add is called by the pipe to register the pipe with
// with the socket.  The pipe is added to the idle list.
extern void nni_sock_pipe_add(nni_sock *, nni_pipe *);

// nni_sock_pipe_rem deregisters the pipe from the socket.  The socket
// will block during close if there are registered pipes outstanding.
extern void nni_sock_pipe_rem(nni_sock *, nni_pipe *);

// nni_sock_pipe_ready lets the socket know the pipe is ready for
// business.  This also calls the socket/protocol specific add function,
// and it may return an error.  A reference count on the pipe is incremented
// on success.  The reference count should be dropped by nni_sock_pipe_closed.
extern int nni_sock_pipe_ready(nni_sock *, nni_pipe *);

// nni_sock_pipe_closed lets the socket know that the pipe is closed.
// This keeps the socket from trying to schedule traffic to it.  It
// also lets the endpoint know about it, to possibly restart a dial
// operation.
extern void nni_sock_pipe_closed(nni_sock *, nni_pipe *);

// Set error codes for applications.  These are only ever
// called from the filter functions in protocols, and thus
// already have the socket lock held.
extern void nni_sock_recverr(nni_sock *, int);
extern void nni_sock_senderr(nni_sock *, int);

// These are socket methods that protocol operations can expect to call.
// Note that each of these should be called without any locks held, since
// the socket can reenter the protocol.

// nni_socket_sendq obtains the upper writeq.  The protocol should
// recieve messages from this, and place them on the appropriate pipe.
extern nni_msgq *nni_sock_sendq(nni_sock *);

// nni_socket_recvq obtains the upper readq.  The protocol should
// inject incoming messages from pipes to it.
extern nni_msgq *nni_sock_recvq(nni_sock *);

// nni_sock_mtx obtains the socket mutex.  This is for protocols to use
// from separate threads; they must not hold the lock for extended periods.
// Additionally, this can only be acquired from separate threads.  The
// synchronous entry points (excluding the send/recv thread workers) will
// be called with this lock already held.  We expose the mutex directly
// here so that protocols can use it to initialize condvars.
extern nni_mtx *nni_sock_mtx(nni_sock *);

extern nni_duration nni_sock_linger(nni_sock *);
extern size_t nni_sock_rcvmaxsz(nni_sock *);

#endif  // CORE_SOCKET_H