SocketOptions.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. using System;
  2. using System.Diagnostics.CodeAnalysis;
  3. using NetMQ.Core;
  4. namespace NetMQ
  5. {
  6. /// <summary>
  7. /// A SocketOptions is simply a convenient way to access the options of a particular socket.
  8. /// This class holds a reference to the socket, and its properties provide a concise way
  9. /// to access that socket's option values -- instead of calling GetSocketOption/SetSocketOption.
  10. /// </summary>
  11. public class SocketOptions
  12. {
  13. /// <summary>
  14. /// The NetMQSocket that this SocketOptions is referencing.
  15. /// </summary>
  16. private readonly NetMQSocket m_socket;
  17. /// <summary>
  18. /// Create a new SocketOptions that references the given NetMQSocket.
  19. /// </summary>
  20. /// <param name="socket">the NetMQSocket for this SocketOptions to hold a reference to</param>
  21. public SocketOptions(NetMQSocket socket)
  22. {
  23. m_socket = socket;
  24. }
  25. /// <summary>
  26. /// Get or set the I/O-thread affinity. This is a 64-bit value used to specify which threads from the I/O thread-pool
  27. /// associated with the socket's context shall handle newly-created connections.
  28. /// 0 means no affinity, meaning that work shall be distributed fairly among all I/O threads.
  29. /// For non-zero values, the lowest bit corresponds to thread 1, second lowest bit to thread 2, and so on.
  30. /// </summary>
  31. public long Affinity
  32. {
  33. get => m_socket.GetSocketOptionLong(ZmqSocketOption.Affinity);
  34. set => m_socket.SetSocketOption(ZmqSocketOption.Affinity, value);
  35. }
  36. /// <summary>
  37. /// Get or set unique identity of the socket, from a message-queueing router's perspective.
  38. /// This is a byte-array of at most 255 bytes.
  39. /// </summary>
  40. [DisallowNull]
  41. public byte[]? Identity
  42. {
  43. get { return m_socket.GetSocketOptionX<byte[]>(ZmqSocketOption.Identity); }
  44. set { m_socket.SetSocketOption(ZmqSocketOption.Identity, value); }
  45. }
  46. /// <summary>
  47. /// Get or set the maximum send or receive data rate for multicast transports on the specified socket.
  48. /// </summary>
  49. public int MulticastRate
  50. {
  51. get => m_socket.GetSocketOption(ZmqSocketOption.Rate);
  52. set => m_socket.SetSocketOption(ZmqSocketOption.Rate, value);
  53. }
  54. /// <summary>
  55. /// Get or set the recovery-interval for multicast transports using the specified socket.
  56. /// This option determines the maximum time that a receiver can be absent from a multicast group
  57. /// before unrecoverable data loss will occur. Default is 10,000 ms (10 seconds).
  58. /// </summary>
  59. public TimeSpan MulticastRecoveryInterval
  60. {
  61. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.RecoveryIvl);
  62. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.RecoveryIvl, value);
  63. }
  64. /// <summary>
  65. /// Get or set the size of the transmit buffer for the specified socket.
  66. /// </summary>
  67. public int SendBuffer
  68. {
  69. get => m_socket.GetSocketOption(ZmqSocketOption.SendBuffer);
  70. set => m_socket.SetSocketOption(ZmqSocketOption.SendBuffer, value);
  71. }
  72. /// <summary>
  73. /// Get or set the size of the receive buffer for the specified socket.
  74. /// A value of zero means that the OS default is in effect.
  75. /// </summary>
  76. public int ReceiveBuffer
  77. {
  78. get => m_socket.GetSocketOption(ZmqSocketOption.ReceiveBuffer);
  79. set => m_socket.SetSocketOption(ZmqSocketOption.ReceiveBuffer, value);
  80. }
  81. /// <summary>
  82. /// Gets whether the last frame received on the socket had the <em>more</em> flag set or not.
  83. /// </summary>
  84. /// <value><c>true</c> if receive more; otherwise, <c>false</c>.</value>
  85. public bool ReceiveMore => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.ReceiveMore);
  86. /// <summary>
  87. /// Get or set the linger period for the specified socket,
  88. /// which determines how long pending messages which have yet to be sent to a peer
  89. /// shall linger in memory after a socket is closed.
  90. /// </summary>
  91. /// <remarks>
  92. /// If socket created with Context default is -1 if socket created without socket (using new keyword) default is zero.
  93. /// If context is used this also affects the termination of context, otherwise this affects the exit of the process.
  94. /// -1: Specifies an infinite linger period. Pending messages shall not be discarded after the socket is closed;
  95. /// attempting to terminate the socket's context shall block until all pending messages have been sent to a peer.
  96. /// 0: Specifies no linger period. Pending messages shall be discarded immediately when the socket is closed.
  97. /// Positive values specify an upper bound for the linger period. Pending messages shall not be discarded after the socket is closed;
  98. /// attempting to terminate the socket's context shall block until either all pending messages have been sent to a peer,
  99. /// or the linger period expires, after which any pending messages shall be discarded.
  100. /// </remarks>
  101. public TimeSpan Linger
  102. {
  103. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.Linger);
  104. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.Linger, value);
  105. }
  106. /// <summary>
  107. /// Get or set the initial reconnection interval for the specified socket.
  108. /// This is the period to wait between attempts to reconnect disconnected peers
  109. /// when using connection-oriented transports. The default is 100 ms.
  110. /// -1 means no reconnection.
  111. /// </summary>
  112. /// <remarks>
  113. /// With ZeroMQ, the reconnection interval may be randomized to prevent reconnection storms
  114. /// in topologies with a large number of peers per socket.
  115. /// </remarks>
  116. public TimeSpan ReconnectInterval
  117. {
  118. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.ReconnectIvl);
  119. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.ReconnectIvl, value);
  120. }
  121. /// <summary>
  122. /// Get or set the maximum reconnection interval for the specified socket.
  123. /// This is the maximum period to shall wait between attempts
  124. /// to reconnect. On each reconnect attempt, the previous interval shall be doubled
  125. /// until this maximum period is reached.
  126. /// The default value of zero means no exponential backoff is performed.
  127. /// </summary>
  128. /// <remarks>
  129. /// This is the maximum period NetMQ shall wait between attempts
  130. /// to reconnect. On each reconnect attempt, the previous interval shall be doubled
  131. /// until this maximum period is reached.
  132. /// This allows for an exponential backoff strategy.
  133. /// The default value of zero means no exponential backoff is performed
  134. /// and reconnect interval calculations are only based on ReconnectIvl.
  135. /// </remarks>
  136. public TimeSpan ReconnectIntervalMax
  137. {
  138. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.ReconnectIvlMax);
  139. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.ReconnectIvlMax, value);
  140. }
  141. /// <summary>
  142. /// Get or set the maximum length of the queue of outstanding peer connections
  143. /// for the specified socket. This only applies to connection-oriented transports.
  144. /// Default is 100.
  145. /// </summary>
  146. public int Backlog
  147. {
  148. get => m_socket.GetSocketOption(ZmqSocketOption.Backlog);
  149. set => m_socket.SetSocketOption(ZmqSocketOption.Backlog, value);
  150. }
  151. /// <summary>
  152. /// Get or set the upper limit to the size for inbound messages.
  153. /// If a peer sends a message larger than this it is disconnected.
  154. /// The default value is -1, which means no limit.
  155. /// </summary>
  156. public long MaxMsgSize
  157. {
  158. get => m_socket.GetSocketOptionLong(ZmqSocketOption.MaxMessageSize);
  159. set => m_socket.SetSocketOption(ZmqSocketOption.MaxMessageSize, value);
  160. }
  161. /// <summary>
  162. /// Get or set the high-water-mark for transmission.
  163. /// This is a hard limit on the number of messages that are allowed to queue up
  164. /// before mitigative action is taken.
  165. /// The default is 1000.
  166. /// </summary>
  167. public int SendHighWatermark
  168. {
  169. get => m_socket.GetSocketOption(ZmqSocketOption.SendHighWatermark);
  170. set => m_socket.SetSocketOption(ZmqSocketOption.SendHighWatermark, value);
  171. }
  172. /// <summary>
  173. /// Get or set the high-water-mark for reception.
  174. /// This is a hard limit on the number of messages that are allowed to queue up
  175. /// before mitigative action is taken.
  176. /// The default is 1000.
  177. /// </summary>
  178. public int ReceiveHighWatermark
  179. {
  180. get => m_socket.GetSocketOption(ZmqSocketOption.ReceiveHighWatermark);
  181. set => m_socket.SetSocketOption(ZmqSocketOption.ReceiveHighWatermark, value);
  182. }
  183. /// <summary>
  184. /// The low-water mark for message transmission.
  185. /// This is the number of messages that should be processed before transmission is
  186. /// unblocked (in case it was blocked by reaching high-watermark). The default value is
  187. /// calculated using relevant high-watermark (HWM): HWM > 2048 ? HWM - 1024 : (HWM + 1) / 2
  188. /// </summary>
  189. public int SendLowWatermark
  190. {
  191. get => m_socket.GetSocketOption(ZmqSocketOption.SendLowWatermark);
  192. set => m_socket.SetSocketOption(ZmqSocketOption.SendLowWatermark, value);
  193. }
  194. /// <summary>
  195. /// The low-water mark for message reception.
  196. /// This is the number of messages that should be processed before reception is
  197. /// unblocked (in case it was blocked by reaching high-watermark). The default value is
  198. /// calculated using relevant high-watermark (HWM): HWM > 2048 ? HWM - 1024 : (HWM + 1) / 2
  199. /// </summary>
  200. public int ReceiveLowWatermark
  201. {
  202. get => m_socket.GetSocketOption(ZmqSocketOption.ReceiveLowWatermark);
  203. set => m_socket.SetSocketOption(ZmqSocketOption.ReceiveLowWatermark, value);
  204. }
  205. /// <summary>
  206. /// Get or set the time-to-live (maximum number of hops) that outbound multicast packets
  207. /// are allowed to propagate.
  208. /// The default value of 1 means that the multicast packets don't leave the local network.
  209. /// </summary>
  210. public int MulticastHops
  211. {
  212. get => m_socket.GetSocketOption(ZmqSocketOption.MulticastHops);
  213. set => m_socket.SetSocketOption(ZmqSocketOption.MulticastHops, value);
  214. }
  215. /// <summary>
  216. /// Get or set whether the underlying socket is for IPv4 only (not IPv6),
  217. /// as opposed to one that allows connections with either IPv4 or IPv6.
  218. /// </summary>
  219. public bool IPv4Only
  220. {
  221. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.IPv4Only);
  222. set => m_socket.SetSocketOption(ZmqSocketOption.IPv4Only, value);
  223. }
  224. /// <summary>
  225. /// Get the last endpoint bound for TCP and IPC transports.
  226. /// The returned value will be a string in the form of a ZMQ DSN.
  227. /// </summary>
  228. /// <remarks>
  229. /// If the TCP host is ANY, indicated by a *, then the returned address
  230. /// will be 0.0.0.0 (for IPv4).
  231. /// </remarks>
  232. public string? LastEndpoint => m_socket.GetSocketOptionX<string>(ZmqSocketOption.LastEndpoint);
  233. /// <summary>
  234. /// Set the RouterSocket behavior when an unroutable message is encountered.
  235. /// A value of false is the default and discards the message silently when it cannot be routed.
  236. /// A value of true causes throw of HostUnreachableException if the message cannot be routed.
  237. /// </summary>
  238. public bool RouterMandatory
  239. {
  240. set => m_socket.SetSocketOption(ZmqSocketOption.RouterMandatory, value);
  241. }
  242. /// <summary>
  243. /// Get or set whether to use TCP keepalive.
  244. /// </summary>
  245. /// <remarks>
  246. /// When Keepalive is enabled, then your socket will periodically send an empty keepalive probe packet
  247. /// with the ACK flag on. The remote endpoint does not need to support keepalive at all, just TCP/IP.
  248. /// If you receive a reply to your keepalive probe, you can assume that the connection is still up and running.
  249. /// This procedure is useful because if the other peers lose their connection (for example, by rebooting)
  250. /// you will notice that the connection is broken, even if you don't have traffic on it.
  251. /// If the keepalive probes are not replied to by your peer, you can assert that the connection
  252. /// cannot be considered valid and then take the corrective action.
  253. /// </remarks>
  254. public bool TcpKeepalive
  255. {
  256. get => m_socket.GetSocketOption(ZmqSocketOption.TcpKeepalive) == 1;
  257. set => m_socket.SetSocketOption(ZmqSocketOption.TcpKeepalive, value ? 1 : 0);
  258. // TODO: What about the value -1, which means use the OS default? jh
  259. // See http://api.zeromq.org/3-2:zmq-getsockopt
  260. }
  261. /// <summary>
  262. /// Get or set the keep-alive time - the duration between two keepalive transmissions in idle condition.
  263. /// The TCP keepalive period is required by socket implementers to be configurable and by default is
  264. /// set to no less than 2 hours.
  265. /// </summary>
  266. public TimeSpan TcpKeepaliveIdle
  267. {
  268. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.TcpKeepaliveIdle);
  269. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.TcpKeepaliveIdle, value);
  270. // TODO: What about the value -1, which means use the OS default? jh
  271. // See http://api.zeromq.org/3-2:zmq-getsockopt
  272. }
  273. /// <summary>
  274. /// Get or set the TCP keep-alive interval - the duration between two keepalive transmission if no response was received to a previous keepalive probe.
  275. /// </summary>
  276. /// <remarks>
  277. /// By default a keepalive packet is sent every 2 hours or 7,200,000 milliseconds
  278. /// (TODO: Check these comments concerning default values! jh)
  279. /// if no other data have been carried over the TCP connection.
  280. /// If there is no response to a keepalive, it is repeated once every KeepAliveInterval seconds.
  281. /// The default is one second.
  282. /// </remarks>
  283. public TimeSpan TcpKeepaliveInterval
  284. {
  285. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.TcpKeepaliveIntvl);
  286. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.TcpKeepaliveIntvl, value);
  287. }
  288. /// <summary>
  289. /// Get or set the attach-on-connect value.
  290. /// If set to true, this will delay the attachment of a pipe on connect until
  291. /// the underlying connection has completed. This will cause the socket
  292. /// to block if there are no other connections, but will prevent queues
  293. /// from filling on pipes awaiting connection.
  294. /// Default is false.
  295. /// </summary>
  296. public bool DelayAttachOnConnect
  297. {
  298. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.DelayAttachOnConnect);
  299. set => m_socket.SetSocketOption(ZmqSocketOption.DelayAttachOnConnect, value);
  300. }
  301. /// <summary>
  302. /// This applies only to publisher sockets.
  303. /// Set whether to send all subscription messages upstream, not just unique ones.
  304. /// The default is false.
  305. /// </summary>
  306. public bool XPubVerbose
  307. {
  308. set => m_socket.SetSocketOption(ZmqSocketOption.XpubVerbose, value);
  309. }
  310. /// <summary>
  311. /// This applies only to publisher sockets.
  312. /// Set whether to support broadcast functionality
  313. /// </summary>
  314. public bool XPubBroadcast
  315. {
  316. set => m_socket.SetSocketOption(ZmqSocketOption.XPublisherBroadcast, value);
  317. }
  318. /// <summary>
  319. /// This applies only to router sockets.
  320. /// Set whether RouterSocket allows non-zmq tcp connects.
  321. /// If true, router socket accepts non-zmq tcp connections
  322. /// </summary>
  323. public bool RouterRawSocket
  324. {
  325. set => m_socket.SetSocketOption(ZmqSocketOption.RouterRawSocket, value);
  326. }
  327. /// <summary>
  328. /// When enabled new router connections with same identity take over old ones
  329. /// </summary>
  330. public bool RouterHandover
  331. {
  332. set => m_socket.SetSocketOption(ZmqSocketOption.RouterHandover, value);
  333. }
  334. /// <summary>
  335. /// Get or set the byte-order: big-endian, vs little-endian.
  336. /// </summary>
  337. public Endianness Endian
  338. {
  339. get => m_socket.GetSocketOptionX<Endianness>(ZmqSocketOption.Endian);
  340. set => m_socket.SetSocketOption(ZmqSocketOption.Endian, value);
  341. }
  342. /// <summary>
  343. /// Enable Manual Publisher, Publisher won't add subscription automatically,
  344. /// Subscribe must be called on the socket to add subscription.
  345. /// </summary>
  346. public bool ManualPublisher
  347. {
  348. set => m_socket.SetSocketOption(ZmqSocketOption.XPublisherManual, value);
  349. }
  350. /// <summary>
  351. /// Disable socket time-wait
  352. /// </summary>
  353. public bool DisableTimeWait
  354. {
  355. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.DisableTimeWait);
  356. set => m_socket.SetSocketOption(ZmqSocketOption.DisableTimeWait, value);
  357. }
  358. /// <summary>
  359. /// Get the last PEER allocated routing id
  360. /// </summary>
  361. public byte[]? LastPeerRoutingId => m_socket.GetSocketOptionX<byte[]>(ZmqSocketOption.LastPeerRoutingId);
  362. /// <summary>
  363. /// Controls the maximum datagram size for PGM.
  364. /// </summary>
  365. public int PgmMaxTransportServiceDataUnitLength
  366. {
  367. get => m_socket.GetSocketOptionX<int>(ZmqSocketOption.PgmMaxTransportServiceDataUnitLength);
  368. set => m_socket.SetSocketOption(ZmqSocketOption.PgmMaxTransportServiceDataUnitLength, value);
  369. }
  370. /// <summary>
  371. /// Defines whether the socket will act as server for CURVE security.
  372. /// A value of true means the socket will act as CURVE server.
  373. /// A value of false means the socket will not act as CURVE server, and its security role then depends on other option settings.
  374. /// Setting this to false shall reset the socket security to NULL.
  375. /// When you set this you must also set the server's secret key. A server socket does not need to know its own public key.
  376. /// </summary>
  377. public bool CurveServer
  378. {
  379. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.CurveServer);
  380. set => m_socket.SetSocketOption(ZmqSocketOption.CurveServer, value);
  381. }
  382. /// <summary>
  383. /// Sets the socket's long term curve key pair.
  384. /// You must set this on both CURVE client and server sockets.
  385. /// You can provide the key as 32 binary bytes.
  386. /// To generate a certificate, use <see cref="NetMQCertificate"/>.
  387. /// </summary>
  388. public NetMQCertificate CurveCertificate
  389. {
  390. set
  391. {
  392. if (value.SecretKey == null)
  393. throw new ArgumentException("NetMQCertificate must have a secret key", nameof(value));
  394. m_socket.SetSocketOption(ZmqSocketOption.CurveSecretKey, value.SecretKey);
  395. m_socket.SetSocketOption(ZmqSocketOption.CurvePublicKey, value.PublicKey);
  396. }
  397. }
  398. /// <summary>
  399. /// Sets the socket's long term server key.
  400. /// You must set this on CURVE client sockets.
  401. /// You can provide the key as 32 binary bytes.
  402. /// This key must have been generated together with the server's secret key.
  403. /// To generate a public/secret key pair, use <see cref="NetMQCertificate"/>.
  404. /// </summary>
  405. [DisallowNull]
  406. public byte[]? CurveServerKey
  407. {
  408. get => m_socket.GetSocketOptionX<byte[]>(ZmqSocketOption.CurveServerKey);
  409. set => m_socket.SetSocketOption(ZmqSocketOption.CurveServerKey, value);
  410. }
  411. /// <summary>
  412. /// Sets the socket's long term server certificate.
  413. /// You must set this on CURVE client sockets.
  414. /// You can provide the key as 32 binary bytes.
  415. /// This key must have been generated together with the server's secret key.
  416. /// To generate a certificate, use <see cref="NetMQCertificate"/>.
  417. /// </summary>
  418. public NetMQCertificate CurveServerCertificate
  419. {
  420. set => m_socket.SetSocketOption(ZmqSocketOption.CurveServerKey, value.PublicKey);
  421. }
  422. /// <summary>
  423. /// If remote peer receives a PING message and doesn't receive another
  424. /// message within the ttl value, it should close the connection
  425. /// (measured in tenths of a second)
  426. /// </summary>
  427. public TimeSpan HeartbeatTtl
  428. {
  429. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatTtl);
  430. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatTtl, value);
  431. }
  432. /// <summary>
  433. /// Time in milliseconds between sending heartbeat PING messages.
  434. /// </summary>
  435. public TimeSpan HeartbeatInterval
  436. {
  437. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatInterval);
  438. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatInterval, value);
  439. }
  440. /// <summary>
  441. /// Time in milliseconds to wait for a PING response before disconnecting
  442. /// </summary>
  443. public TimeSpan HeartbeatTimeout
  444. {
  445. get => m_socket.GetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatTimeout);
  446. set => m_socket.SetSocketOptionTimeSpan(ZmqSocketOption.HeartbeatTimeout, value);
  447. }
  448. /// <summary>
  449. /// Set message to send to peer upon connecting
  450. /// </summary>
  451. public byte[] HelloMessage
  452. {
  453. set => m_socket.SetSocketOption(ZmqSocketOption.HelloMessage, value);
  454. }
  455. /// <summary>
  456. /// relax strict alternation between request and reply on REQ sockets
  457. /// </summary>
  458. public bool Relaxed
  459. {
  460. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.Relaxed);
  461. set => m_socket.SetSocketOption(ZmqSocketOption.Relaxed, value);
  462. }
  463. /// <summary>
  464. /// match replies with requests on REQ sockets
  465. /// </summary>
  466. public bool Correlate
  467. {
  468. get => m_socket.GetSocketOptionX<bool>(ZmqSocketOption.Correlate);
  469. set => m_socket.SetSocketOption(ZmqSocketOption.Correlate, value);
  470. }
  471. }
  472. }