├── .gitignore ├── .godocdown.md ├── .todo2 ├── .travis.yml ├── AUTHORS ├── README.md ├── examples ├── client │ └── client.go └── server │ └── server.go ├── gozmqfix ├── LICENSE ├── README.md ├── fix.go ├── main.go ├── main_test.go ├── zmqstruct.go └── zmqstruct_test.go ├── gozmqgen ├── README.md ├── header.txt ├── main.go ├── main_test.go └── template.txt ├── zmq.go ├── zmq_2_2.go ├── zmq_2_x.go ├── zmq_3_x.go ├── zmq_3_x_test.go ├── zmq_4_x.go ├── zmq_test.go ├── zmq_unix.go ├── zmq_windows.go ├── zmqgen_2_1.go ├── zmqgen_2_2.go ├── zmqgen_3_2.go └── zmqgen_4_0.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.[568vq] 4 | [568vq].out 5 | *.cgo1.go 6 | *.cgo2.c 7 | _cgo_defun.c 8 | _cgo_gotypes.go 9 | _cgo_export.* 10 | *.so 11 | _obj 12 | _test 13 | _testmain.go 14 | *.exe 15 | .cache 16 | -------------------------------------------------------------------------------- /.godocdown.md: -------------------------------------------------------------------------------- 1 | # Go (golang) Bindings for 0mq (zmq, zeromq) 2 | 3 | [![Build Status](https://travis-ci.org/alecthomas/gozmq.png)](https://travis-ci.org/alecthomas/gozmq) 4 | 5 | This package implements [Go](http://golang.org) (golang) bindings for 6 | the [0mq](http://zeromq.org) C API. 7 | 8 | It is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 9 | 10 | GoZMQ [does not](#zero-copy) support zero-copy. 11 | 12 | A full list of examples is included in the [zguide](https://github.com/imatix/zguide/tree/master/examples/Go). 13 | 14 | Note that this is *not* the same as [this 15 | implementation](http://github.com/boggle/gozero) or [this 16 | implementation](http://code.google.com/p/gozmq/). 17 | 18 | ## Upgrading 19 | 20 | GoZMQ has made some public changes that will break old code. Fortunately, we've also written a tool based on `go fix` that will upgrade your code for you! Here's how to run it over your source (after making a backup of course): 21 | 22 | go get github.com/alecthomas/gozmq/gozmqfix 23 | cd $YOUR_SOURCE_DIR 24 | gozmqfix . 25 | 26 | ## Installing 27 | 28 | GoZMQ currently supports ZMQ 2.1.x, 2.2.x and *basic* support for 3.x. Following are instructions on how to compile against these versions. 29 | 30 | Install gozmq with: 31 | 32 | go get github.com/alecthomas/gozmq 33 | 34 | This implementation works currently against:: ZeroMQ 2.2.x 35 | 36 | ### ZeroMQ 2.1.x 37 | 38 | If you're using ZeroMQ 2.1.x, install with: 39 | 40 | go get -tags zmq_2_1 github.com/alecthomas/gozmq 41 | 42 | ### ZeroMQ 3.x 43 | 44 | There is *basic* support for ZeroMQ 3.x. Install with: 45 | 46 | go get -tags zmq_3_x github.com/alecthomas/gozmq 47 | 48 | ### Troubleshooting 49 | 50 | #### Go can't find ZMQ 51 | 52 | If the go tool can't find zmq and you know it is installed, you may need to override the C compiler/linker flags. 53 | 54 | eg. If you installed zmq into `/opt/zmq` you might try: 55 | 56 | CGO_CFLAGS=-I/opt/zmq/include CGO_LDFLAGS=-L/opt/zmq/lib \ 57 | go get github.com/alecthomas/gozmq 58 | 59 | #### Mismatch in version of ZMQ 60 | 61 | If you get errors like this with 'go get' or 'go build': 62 | 63 | 1: error: 'ZMQ_FOO' undeclared (first use in this function) 64 | 65 | There are two possibilities: 66 | 67 | 1. Your version of zmq is *very* old. In this case you will need to download and build zmq yourself. 68 | 2. You are building gozmq against the wrong version of zmq. See the [installation](#installation) instructions for details on how to target the correct version. 69 | 70 | ## Differences from the C API 71 | 72 | The API implemented by this package does not attempt to expose 73 | `zmq_msg_t` at all. Instead, `Recv()` and `Send()` both operate on byte 74 | slices, allocating and freeing the memory automatically. Currently this 75 | requires copying to/from C malloced memory, but a future implementation 76 | may be able to avoid this to a certain extent. 77 | 78 | All major features are supported: contexts, sockets, devices, and polls. 79 | 80 | ## Example 81 | 82 | Here are direct translations of some of the examples from [this blog 83 | post](http://nichol.as/zeromq-an-introduction). 84 | 85 | A simple echo server: 86 | 87 | ```go 88 | package main 89 | 90 | import zmq "github.com/alecthomas/gozmq" 91 | 92 | func main() { 93 | context, _ := zmq.NewContext() 94 | socket, _ := context.NewSocket(zmq.REP) 95 | socket.Bind("tcp://127.0.0.1:5000") 96 | socket.Bind("tcp://127.0.0.1:6000") 97 | 98 | for { 99 | msg, _ := socket.Recv(0) 100 | println("Got", string(msg)) 101 | socket.Send(msg, 0) 102 | } 103 | } 104 | ``` 105 | 106 | A simple client for the above server: 107 | 108 | ```go 109 | package main 110 | 111 | import "fmt" 112 | import zmq "github.com/alecthomas/gozmq" 113 | 114 | func main() { 115 | context, _ := zmq.NewContext() 116 | socket, _ := context.NewSocket(zmq.REQ) 117 | socket.Connect("tcp://127.0.0.1:5000") 118 | socket.Connect("tcp://127.0.0.1:6000") 119 | 120 | for i := 0; i < 10; i++ { 121 | msg := fmt.Sprintf("msg %d", i) 122 | socket.Send([]byte(msg), 0) 123 | println("Sending", msg) 124 | socket.Recv(0) 125 | } 126 | } 127 | ``` 128 | 129 | ## Caveats 130 | 131 | ### Zero-copy 132 | 133 | GoZMQ does not support zero-copy. 134 | 135 | GoZMQ does not attempt to expose `zmq_msg_t` at all. Instead, `Recv()` and `Send()` 136 | both operate on byte slices, allocating and freeing the memory automatically. 137 | Currently this requires copying to/from C malloced memory, but a future 138 | implementation may be able to avoid this to a certain extent. 139 | 140 | 141 | ### Memory management 142 | 143 | It's not entirely clear from the 0mq documentation how memory for 144 | `zmq_msg_t` and packet data is managed once 0mq takes ownership. After 145 | digging into the source a little, this package operates under the 146 | following (educated) assumptions: 147 | 148 | - References to `zmq_msg_t` structures are not held by the C API 149 | beyond the duration of any function call. 150 | - Packet data is reference counted internally by the C API. The count 151 | is incremented when a packet is queued for delivery to a destination 152 | (the inference being that for delivery to N destinations, the 153 | reference count will be incremented N times) and decremented once 154 | the packet has either been delivered or errored. 155 | 156 | {{ .EmitUsage }} 157 | 158 | *(generated from .[godocdown](https://github.com/robertkrimen/godocdown).md with `godocdown github.com/alecthomas/gozmq > README.md`)* 159 | -------------------------------------------------------------------------------- /.todo2: -------------------------------------------------------------------------------- 1 | { 2 | "title": "GoZMQ - ZMQ bindings for Go", 3 | "tasks": [] 4 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sudo apt-get install libzmq3-dev 3 | language: go 4 | go: 1.1.1 5 | install: go get -tags zmq_3_x -d -v ./... && go build -tags zmq_3_x -v ./... 6 | script: go test -v -tags zmq_3_x ./... 7 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The GoZmq package was originally written by Alec Thomas . 2 | 3 | Thanks to the following frequent contributors: 4 | 5 | @mcgoo Jim McGrath (https://github.com/mcgoo) 6 | @jtacoma Joshua Tacoma (https://github.com/jtacoma) 7 | @jhawk28 8 | 9 | And many others. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # _NOTE:_ These gozmq bindings are in maintenance mode. Only critical bugs will be fixed. Henceforth I would suggest using [@pebbe's](https://github.com/pebbe) actively maintained bindings for [zmq2](https://github.com/pebbe/zmq2), [zmq3](https://github.com/pebbe/zmq3) and [zmq4](https://github.com/pebbe/zmq4). 2 | 3 | ## Go (golang) Bindings for 0mq (zmq, zeromq) 4 | 5 | [![Build Status](https://travis-ci.org/alecthomas/gozmq.png)](https://travis-ci.org/alecthomas/gozmq) 6 | 7 | This package implements [Go](http://golang.org) (golang) bindings for 8 | the [0mq](http://zeromq.org) C API. 9 | 10 | GoZMQ [does not](#zero-copy) support zero-copy. 11 | 12 | A full list of examples is included in the [zguide](https://github.com/imatix/zguide/tree/master/examples/Go). 13 | 14 | Note that this is *not* the same as [this 15 | implementation](http://github.com/boggle/gozero) or [this 16 | implementation](http://code.google.com/p/gozmq/). 17 | 18 | ## Upgrading 19 | 20 | GoZMQ has made some public changes that will break old code. Fortunately, we've also written a tool based on `go fix` that will upgrade your code for you! Here's how to run it over your source (after making a backup of course): 21 | 22 | go get github.com/alecthomas/gozmq/gozmqfix 23 | cd $YOUR_SOURCE_DIR 24 | gozmqfix . 25 | 26 | ## Installing 27 | 28 | GoZMQ currently supports ZMQ 2.1.x, 2.2.x, 3.x and 4.x. Following are instructions on how to compile against these versions. 29 | 30 | For ZeroMQ 2.2.x install with: 31 | 32 | go get github.com/alecthomas/gozmq 33 | 34 | For 2.1.x install with: 35 | 36 | go get -tags zmq_2_1 github.com/alecthomas/gozmq 37 | 38 | For 3.x install with: 39 | 40 | go get -tags zmq_3_x github.com/alecthomas/gozmq 41 | 42 | For 4.x install with: 43 | 44 | go get -tags zmq_4_x github.com/alecthomas/gozmq 45 | 46 | ### Troubleshooting 47 | 48 | #### Go can't find ZMQ 49 | 50 | If the go tool can't find zmq and you know it is installed, you may need to override the C compiler/linker flags. 51 | 52 | eg. If you installed zmq into `/opt/zmq` you might try: 53 | 54 | CGO_CFLAGS=-I/opt/zmq/include CGO_LDFLAGS=-L/opt/zmq/lib \ 55 | go get github.com/alecthomas/gozmq 56 | 57 | #### Mismatch in version of ZMQ 58 | 59 | If you get errors like this with 'go get' or 'go build': 60 | 61 | 1: error: 'ZMQ_FOO' undeclared (first use in this function) 62 | 63 | There are two possibilities: 64 | 65 | 1. Your version of zmq is *very* old. In this case you will need to download and build zmq yourself. 66 | 2. You are building gozmq against the wrong version of zmq. See the [installation](#installation) instructions for details on how to target the correct version. 67 | 68 | ## Differences from the C API 69 | 70 | The API implemented by this package does not attempt to expose 71 | `zmq_msg_t` at all. Instead, `Recv()` and `Send()` both operate on byte 72 | slices, allocating and freeing the memory automatically. Currently this 73 | requires copying to/from C malloced memory, but a future implementation 74 | may be able to avoid this to a certain extent. 75 | 76 | All major features are supported: contexts, sockets, devices, and polls. 77 | 78 | ## Example 79 | 80 | Here are direct translations of some of the examples from [this blog 81 | post](http://nichol.as/zeromq-an-introduction). 82 | 83 | A simple echo server: 84 | 85 | ```go 86 | package main 87 | 88 | import zmq "github.com/alecthomas/gozmq" 89 | 90 | func main() { 91 | context, _ := zmq.NewContext() 92 | socket, _ := context.NewSocket(zmq.REP) 93 | socket.Bind("tcp://127.0.0.1:5000") 94 | socket.Bind("tcp://127.0.0.1:6000") 95 | 96 | for { 97 | msg, _ := socket.Recv(0) 98 | println("Got", string(msg)) 99 | socket.Send(msg, 0) 100 | } 101 | } 102 | ``` 103 | 104 | A simple client for the above server: 105 | 106 | ```go 107 | package main 108 | 109 | import "fmt" 110 | import zmq "github.com/alecthomas/gozmq" 111 | 112 | func main() { 113 | context, _ := zmq.NewContext() 114 | socket, _ := context.NewSocket(zmq.REQ) 115 | socket.Connect("tcp://127.0.0.1:5000") 116 | socket.Connect("tcp://127.0.0.1:6000") 117 | 118 | for i := 0; i < 10; i++ { 119 | msg := fmt.Sprintf("msg %d", i) 120 | socket.Send([]byte(msg), 0) 121 | println("Sending", msg) 122 | socket.Recv(0) 123 | } 124 | } 125 | ``` 126 | 127 | ## Caveats 128 | 129 | ### Zero-copy 130 | 131 | GoZMQ does not support zero-copy. 132 | 133 | GoZMQ does not attempt to expose `zmq_msg_t` at all. Instead, `Recv()` and `Send()` 134 | both operate on byte slices, allocating and freeing the memory automatically. 135 | Currently this requires copying to/from C malloced memory, but a future 136 | implementation may be able to avoid this to a certain extent. 137 | 138 | 139 | ### Memory management 140 | 141 | It's not entirely clear from the 0mq documentation how memory for 142 | `zmq_msg_t` and packet data is managed once 0mq takes ownership. After 143 | digging into the source a little, this package operates under the 144 | following (educated) assumptions: 145 | 146 | - References to `zmq_msg_t` structures are not held by the C API 147 | beyond the duration of any function call. 148 | - Packet data is reference counted internally by the C API. The count 149 | is incremented when a packet is queued for delivery to a destination 150 | (the inference being that for delivery to N destinations, the 151 | reference count will be incremented N times) and decremented once 152 | the packet has either been delivered or errored. 153 | 154 | ## Usage 155 | 156 | ```go 157 | const ( 158 | // NewSocket types 159 | PAIR = SocketType(C.ZMQ_PAIR) 160 | PUB = SocketType(C.ZMQ_PUB) 161 | SUB = SocketType(C.ZMQ_SUB) 162 | REQ = SocketType(C.ZMQ_REQ) 163 | REP = SocketType(C.ZMQ_REP) 164 | DEALER = SocketType(C.ZMQ_DEALER) 165 | ROUTER = SocketType(C.ZMQ_ROUTER) 166 | PULL = SocketType(C.ZMQ_PULL) 167 | PUSH = SocketType(C.ZMQ_PUSH) 168 | XPUB = SocketType(C.ZMQ_XPUB) 169 | XSUB = SocketType(C.ZMQ_XSUB) 170 | 171 | // Deprecated aliases 172 | XREQ = DEALER 173 | XREP = ROUTER 174 | UPSTREAM = PULL 175 | DOWNSTREAM = PUSH 176 | 177 | // NewSocket options 178 | AFFINITY = UInt64SocketOption(C.ZMQ_AFFINITY) 179 | IDENTITY = StringSocketOption(C.ZMQ_IDENTITY) 180 | SUBSCRIBE = StringSocketOption(C.ZMQ_SUBSCRIBE) 181 | UNSUBSCRIBE = StringSocketOption(C.ZMQ_UNSUBSCRIBE) 182 | RATE = Int64SocketOption(C.ZMQ_RATE) 183 | RECOVERY_IVL = Int64SocketOption(C.ZMQ_RECOVERY_IVL) 184 | SNDBUF = UInt64SocketOption(C.ZMQ_SNDBUF) 185 | RCVBUF = UInt64SocketOption(C.ZMQ_RCVBUF) 186 | FD = Int64SocketOption(C.ZMQ_FD) 187 | EVENTS = UInt64SocketOption(C.ZMQ_EVENTS) 188 | TYPE = UInt64SocketOption(C.ZMQ_TYPE) 189 | LINGER = IntSocketOption(C.ZMQ_LINGER) 190 | RECONNECT_IVL = IntSocketOption(C.ZMQ_RECONNECT_IVL) 191 | RECONNECT_IVL_MAX = IntSocketOption(C.ZMQ_RECONNECT_IVL_MAX) 192 | BACKLOG = IntSocketOption(C.ZMQ_BACKLOG) 193 | 194 | // Send/recv options 195 | SNDMORE = SendRecvOption(C.ZMQ_SNDMORE) 196 | ) 197 | ``` 198 | 199 | ```go 200 | const ( 201 | POLLIN = PollEvents(C.ZMQ_POLLIN) 202 | POLLOUT = PollEvents(C.ZMQ_POLLOUT) 203 | POLLERR = PollEvents(C.ZMQ_POLLERR) 204 | ) 205 | ``` 206 | 207 | ```go 208 | const ( 209 | STREAMER = DeviceType(C.ZMQ_STREAMER) 210 | FORWARDER = DeviceType(C.ZMQ_FORWARDER) 211 | QUEUE = DeviceType(C.ZMQ_QUEUE) 212 | ) 213 | ``` 214 | 215 | ```go 216 | const ( 217 | RCVTIMEO = IntSocketOption(C.ZMQ_RCVTIMEO) 218 | SNDTIMEO = IntSocketOption(C.ZMQ_SNDTIMEO) 219 | ) 220 | ``` 221 | 222 | ```go 223 | const ( 224 | RCVMORE = UInt64SocketOption(C.ZMQ_RCVMORE) 225 | RECOVERY_IVL_MSEC = Int64SocketOption(C.ZMQ_RECOVERY_IVL_MSEC) 226 | SWAP = Int64SocketOption(C.ZMQ_SWAP) 227 | MCAST_LOOP = Int64SocketOption(C.ZMQ_MCAST_LOOP) 228 | HWM = UInt64SocketOption(C.ZMQ_HWM) 229 | NOBLOCK = SendRecvOption(C.ZMQ_NOBLOCK) 230 | 231 | // Forwards-compatible aliases: 232 | DONTWAIT = NOBLOCK 233 | ) 234 | ``` 235 | 236 | ```go 237 | const ( 238 | RCVMORE = IntSocketOption(C.ZMQ_RCVMORE) 239 | SNDHWM = IntSocketOption(C.ZMQ_SNDHWM) 240 | RCVHWM = IntSocketOption(C.ZMQ_RCVHWM) 241 | 242 | // TODO Not documented in the man page... 243 | //LAST_ENDPOINT = UInt64SocketOption(C.ZMQ_LAST_ENDPOINT) 244 | FAIL_UNROUTABLE = BoolSocketOption(C.ZMQ_FAIL_UNROUTABLE) 245 | TCP_KEEPALIVE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE) 246 | TCP_KEEPALIVE_CNT = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_CNT) 247 | TCP_KEEPALIVE_IDLE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_IDLE) 248 | TCP_KEEPALIVE_INTVL = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_INTVL) 249 | TCP_ACCEPT_FILTER = StringSocketOption(C.ZMQ_TCP_ACCEPT_FILTER) 250 | 251 | // Message options 252 | MORE = MessageOption(C.ZMQ_MORE) 253 | 254 | // Send/recv options 255 | DONTWAIT = SendRecvOption(C.ZMQ_DONTWAIT) 256 | 257 | // Deprecated aliases 258 | NOBLOCK = DONTWAIT 259 | ) 260 | ``` 261 | 262 | ```go 263 | var ( 264 | // Additional ZMQ errors 265 | ENOTSOCK error = zmqErrno(C.ENOTSOCK) 266 | EFSM error = zmqErrno(C.EFSM) 267 | EINVAL error = zmqErrno(C.EINVAL) 268 | ENOCOMPATPROTO error = zmqErrno(C.ENOCOMPATPROTO) 269 | ETERM error = zmqErrno(C.ETERM) 270 | EMTHREAD error = zmqErrno(C.EMTHREAD) 271 | ) 272 | ``` 273 | 274 | #### func Device 275 | 276 | ```go 277 | func Device(t DeviceType, in, out *Socket) error 278 | ``` 279 | run a zmq_device passing messages between in and out 280 | 281 | #### func Poll 282 | 283 | ```go 284 | func Poll(items []PollItem, timeout time.Duration) (count int, err error) 285 | ``` 286 | Poll ZmqSockets and file descriptors for I/O readiness. Timeout is in 287 | time.Duration. The smallest possible timeout is time.Millisecond for ZeroMQ 288 | version 3 and above, and time.Microsecond for earlier versions. 289 | 290 | #### func Proxy 291 | 292 | ```go 293 | func Proxy(in, out, capture *Socket) error 294 | ``` 295 | run a zmq_proxy with in, out and capture sockets 296 | 297 | #### func Version 298 | 299 | ```go 300 | func Version() (int, int, int) 301 | ``` 302 | void zmq_version (int *major, int *minor, int *patch); 303 | 304 | #### type BoolSocketOption 305 | 306 | ```go 307 | type BoolSocketOption int 308 | ``` 309 | 310 | 311 | #### type Context 312 | 313 | ```go 314 | type Context struct { 315 | } 316 | ``` 317 | 318 | * A context handles socket creation and asynchronous message delivery. * There 319 | should generally be one context per application. 320 | 321 | #### func NewContext 322 | 323 | ```go 324 | func NewContext() (*Context, error) 325 | ``` 326 | Create a new context. 327 | 328 | #### func (*Context) Close 329 | 330 | ```go 331 | func (c *Context) Close() 332 | ``` 333 | 334 | #### func (*Context) IOThreads 335 | 336 | ```go 337 | func (c *Context) IOThreads() (int, error) 338 | ``` 339 | Get a context option. 340 | 341 | #### func (*Context) MaxSockets 342 | 343 | ```go 344 | func (c *Context) MaxSockets() (int, error) 345 | ``` 346 | 347 | #### func (*Context) NewSocket 348 | 349 | ```go 350 | func (c *Context) NewSocket(t SocketType) (*Socket, error) 351 | ``` 352 | Create a new socket. void *zmq_socket (void *context, int type); 353 | 354 | #### func (*Context) SetIOThreads 355 | 356 | ```go 357 | func (c *Context) SetIOThreads(value int) error 358 | ``` 359 | Set a context option. 360 | 361 | #### func (*Context) SetMaxSockets 362 | 363 | ```go 364 | func (c *Context) SetMaxSockets(value int) error 365 | ``` 366 | 367 | #### type DeviceType 368 | 369 | ```go 370 | type DeviceType int 371 | ``` 372 | 373 | 374 | #### type Int64SocketOption 375 | 376 | ```go 377 | type Int64SocketOption int 378 | ``` 379 | 380 | 381 | #### type IntSocketOption 382 | 383 | ```go 384 | type IntSocketOption int 385 | ``` 386 | 387 | 388 | #### type MessageOption 389 | 390 | ```go 391 | type MessageOption int 392 | ``` 393 | 394 | 395 | #### type PollEvents 396 | 397 | ```go 398 | type PollEvents C.short 399 | ``` 400 | 401 | 402 | #### type PollItem 403 | 404 | ```go 405 | type PollItem struct { 406 | Socket *Socket // socket to poll for events on 407 | Fd ZmqOsSocketType // fd to poll for events on as returned from os.File.Fd() 408 | Events PollEvents // event set to poll for 409 | REvents PollEvents // events that were present 410 | } 411 | ``` 412 | 413 | Item to poll for read/write events on, either a *Socket or a file descriptor 414 | 415 | #### type PollItems 416 | 417 | ```go 418 | type PollItems []PollItem 419 | ``` 420 | 421 | a set of items to poll for events on 422 | 423 | #### type SendRecvOption 424 | 425 | ```go 426 | type SendRecvOption int 427 | ``` 428 | 429 | 430 | #### type Socket 431 | 432 | ```go 433 | type Socket struct { 434 | } 435 | ``` 436 | 437 | 438 | #### func (*Socket) Affinity 439 | 440 | ```go 441 | func (s *Socket) Affinity() (uint64, error) 442 | ``` 443 | ZMQ_AFFINITY: Retrieve I/O thread affinity. 444 | 445 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc7 446 | 447 | #### func (*Socket) Backlog 448 | 449 | ```go 450 | func (s *Socket) Backlog() (int, error) 451 | ``` 452 | ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 453 | 454 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc18 455 | 456 | #### func (*Socket) Bind 457 | 458 | ```go 459 | func (s *Socket) Bind(address string) error 460 | ``` 461 | Bind the socket to a listening address. int zmq_bind (void *s, const char 462 | *addr); 463 | 464 | #### func (*Socket) Close 465 | 466 | ```go 467 | func (s *Socket) Close() error 468 | ``` 469 | Shutdown the socket. int zmq_close (void *s); 470 | 471 | #### func (*Socket) Connect 472 | 473 | ```go 474 | func (s *Socket) Connect(address string) error 475 | ``` 476 | Connect the socket to an address. int zmq_connect (void *s, const char *addr); 477 | 478 | #### func (*Socket) Events 479 | 480 | ```go 481 | func (s *Socket) Events() (uint64, error) 482 | ``` 483 | ZMQ_EVENTS: Retrieve socket event state. 484 | 485 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc20 486 | 487 | #### func (*Socket) GetSockOptBool 488 | 489 | ```go 490 | func (s *Socket) GetSockOptBool(option BoolSocketOption) (value bool, err error) 491 | ``` 492 | 493 | #### func (*Socket) GetSockOptInt 494 | 495 | ```go 496 | func (s *Socket) GetSockOptInt(option IntSocketOption) (value int, err error) 497 | ``` 498 | Get an int option from the socket. int zmq_getsockopt (void *s, int option, void 499 | *optval, size_t *optvallen); 500 | 501 | #### func (*Socket) GetSockOptInt64 502 | 503 | ```go 504 | func (s *Socket) GetSockOptInt64(option Int64SocketOption) (value int64, err error) 505 | ``` 506 | Get an int64 option from the socket. int zmq_getsockopt (void *s, int option, 507 | void *optval, size_t *optvallen); 508 | 509 | #### func (*Socket) GetSockOptString 510 | 511 | ```go 512 | func (s *Socket) GetSockOptString(option StringSocketOption) (value string, err error) 513 | ``` 514 | Get a string option from the socket. int zmq_getsockopt (void *s, int option, 515 | void *optval, size_t *optvallen); 516 | 517 | #### func (*Socket) GetSockOptUInt64 518 | 519 | ```go 520 | func (s *Socket) GetSockOptUInt64(option UInt64SocketOption) (value uint64, err error) 521 | ``` 522 | Get a uint64 option from the socket. int zmq_getsockopt (void *s, int option, 523 | void *optval, size_t *optvallen); 524 | 525 | #### func (*Socket) HWM 526 | 527 | ```go 528 | func (s *Socket) HWM() (uint64, error) 529 | ``` 530 | ZMQ_HWM: Retrieve high water mark. 531 | 532 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc5 533 | 534 | #### func (*Socket) Identity 535 | 536 | ```go 537 | func (s *Socket) Identity() (string, error) 538 | ``` 539 | ZMQ_IDENTITY: Retrieve socket identity. 540 | 541 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc8 542 | 543 | #### func (*Socket) Linger 544 | 545 | ```go 546 | func (s *Socket) Linger() (time.Duration, error) 547 | ``` 548 | ZMQ_LINGER: Retrieve linger period for socket shutdown. 549 | 550 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc15 551 | 552 | #### func (*Socket) McastLoop 553 | 554 | ```go 555 | func (s *Socket) McastLoop() (bool, error) 556 | ``` 557 | ZMQ_MCAST_LOOP: Control multicast loop-back. 558 | 559 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc12 560 | 561 | #### func (*Socket) Rate 562 | 563 | ```go 564 | func (s *Socket) Rate() (int64, error) 565 | ``` 566 | ZMQ_RATE: Retrieve multicast data rate. 567 | 568 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc9 569 | 570 | #### func (*Socket) RcvBuf 571 | 572 | ```go 573 | func (s *Socket) RcvBuf() (uint64, error) 574 | ``` 575 | ZMQ_RCVBUF: Retrieve kernel receive buffer size. 576 | 577 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc14 578 | 579 | #### func (*Socket) RcvHWM 580 | 581 | ```go 582 | func (s *Socket) RcvHWM() (int, error) 583 | ``` 584 | ZMQ_RCVHWM: Retrieve high water mark for inbound messages. 585 | 586 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc6 587 | 588 | #### func (*Socket) RcvMore 589 | 590 | ```go 591 | func (s *Socket) RcvMore() (bool, error) 592 | ``` 593 | ZMQ_RCVMORE: More message parts to follow. 594 | 595 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc4 596 | 597 | #### func (*Socket) RcvTimeout 598 | 599 | ```go 600 | func (s *Socket) RcvTimeout() (time.Duration, error) 601 | ``` 602 | ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN. 603 | 604 | See: http://api.zeromq.org/2.2:zmq-getsockopt#toc6 605 | 606 | #### func (*Socket) ReconnectIvl 607 | 608 | ```go 609 | func (s *Socket) ReconnectIvl() (time.Duration, error) 610 | ``` 611 | ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 612 | 613 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc16 614 | 615 | #### func (*Socket) ReconnectIvlMax 616 | 617 | ```go 618 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) 619 | ``` 620 | ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 621 | 622 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc17 623 | 624 | #### func (*Socket) RecoveryIvl 625 | 626 | ```go 627 | func (s *Socket) RecoveryIvl() (time.Duration, error) 628 | ``` 629 | ZMQ_RECOVERY_IVL_MSEC: Get multicast recovery interval in milliseconds. 630 | 631 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc11 632 | 633 | #### func (*Socket) Recv 634 | 635 | ```go 636 | func (s *Socket) Recv(flags SendRecvOption) (data []byte, err error) 637 | ``` 638 | Receive a message from the socket. int zmq_recv (void *s, zmq_msg_t *msg, int 639 | flags); 640 | 641 | #### func (*Socket) RecvMultipart 642 | 643 | ```go 644 | func (s *Socket) RecvMultipart(flags SendRecvOption) (parts [][]byte, err error) 645 | ``` 646 | Receive a multipart message. 647 | 648 | #### func (*Socket) Send 649 | 650 | ```go 651 | func (s *Socket) Send(data []byte, flags SendRecvOption) error 652 | ``` 653 | Send a message to the socket. int zmq_send (void *s, zmq_msg_t *msg, int flags); 654 | 655 | #### func (*Socket) SendMultipart 656 | 657 | ```go 658 | func (s *Socket) SendMultipart(parts [][]byte, flags SendRecvOption) (err error) 659 | ``` 660 | Send a multipart message. 661 | 662 | #### func (*Socket) SetAffinity 663 | 664 | ```go 665 | func (s *Socket) SetAffinity(value uint64) error 666 | ``` 667 | ZMQ_AFFINITY: Set I/O thread affinity. 668 | 669 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc5 670 | 671 | #### func (*Socket) SetBacklog 672 | 673 | ```go 674 | func (s *Socket) SetBacklog(value int) error 675 | ``` 676 | ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 677 | 678 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc18 679 | 680 | #### func (*Socket) SetHWM 681 | 682 | ```go 683 | func (s *Socket) SetHWM(value uint64) error 684 | ``` 685 | ZMQ_HWM: Set high water mark. 686 | 687 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc3 688 | 689 | #### func (*Socket) SetIdentity 690 | 691 | ```go 692 | func (s *Socket) SetIdentity(value string) error 693 | ``` 694 | ZMQ_IDENTITY: Set socket identity. 695 | 696 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc6 697 | 698 | #### func (*Socket) SetLinger 699 | 700 | ```go 701 | func (s *Socket) SetLinger(value time.Duration) error 702 | ``` 703 | ZMQ_LINGER: Set linger period for socket shutdown. 704 | 705 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc15 706 | 707 | #### func (*Socket) SetMcastLoop 708 | 709 | ```go 710 | func (s *Socket) SetMcastLoop(value bool) error 711 | ``` 712 | ZMQ_MCAST_LOOP: Control multicast loop-back. 713 | 714 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc12 715 | 716 | #### func (*Socket) SetRate 717 | 718 | ```go 719 | func (s *Socket) SetRate(value int64) error 720 | ``` 721 | ZMQ_RATE: Set multicast data rate. 722 | 723 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc9 724 | 725 | #### func (*Socket) SetRcvBuf 726 | 727 | ```go 728 | func (s *Socket) SetRcvBuf(value uint64) error 729 | ``` 730 | ZMQ_RCVBUF: Set kernel receive buffer size. 731 | 732 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc14 733 | 734 | #### func (*Socket) SetRcvHWM 735 | 736 | ```go 737 | func (s *Socket) SetRcvHWM(value int) error 738 | ``` 739 | ZMQ_RCVHWM: Set high water mark for inbound messages. 740 | 741 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc4 742 | 743 | #### func (*Socket) SetRcvTimeout 744 | 745 | ```go 746 | func (s *Socket) SetRcvTimeout(value time.Duration) error 747 | ``` 748 | ZMQ_RCVTIMEO: Maximum time before a recv operation returns with EAGAIN. 749 | 750 | See: http://api.zeromq.org/2.2:zmq-setsockopt#toc9 751 | 752 | #### func (*Socket) SetReconnectIvl 753 | 754 | ```go 755 | func (s *Socket) SetReconnectIvl(value time.Duration) error 756 | ``` 757 | ZMQ_RECONNECT_IVL: Set reconnection interval. 758 | 759 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc16 760 | 761 | #### func (*Socket) SetReconnectIvlMax 762 | 763 | ```go 764 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error 765 | ``` 766 | ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 767 | 768 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc17 769 | 770 | #### func (*Socket) SetRecoveryIvl 771 | 772 | ```go 773 | func (s *Socket) SetRecoveryIvl(value time.Duration) error 774 | ``` 775 | ZMQ_RECOVERY_IVL_MSEC: Set multicast recovery interval in milliseconds. 776 | 777 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc11 778 | 779 | #### func (*Socket) SetSndBuf 780 | 781 | ```go 782 | func (s *Socket) SetSndBuf(value uint64) error 783 | ``` 784 | ZMQ_SNDBUF: Set kernel transmit buffer size. 785 | 786 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc13 787 | 788 | #### func (*Socket) SetSndHWM 789 | 790 | ```go 791 | func (s *Socket) SetSndHWM(value int) error 792 | ``` 793 | ZMQ_SNDHWM: Set high water mark for outbound messages. 794 | 795 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc3 796 | 797 | #### func (*Socket) SetSndTimeout 798 | 799 | ```go 800 | func (s *Socket) SetSndTimeout(value time.Duration) error 801 | ``` 802 | ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN. 803 | 804 | See: http://api.zeromq.org/2.2:zmq-setsockopt#toc10 805 | 806 | #### func (*Socket) SetSockOptInt 807 | 808 | ```go 809 | func (s *Socket) SetSockOptInt(option IntSocketOption, value int) error 810 | ``` 811 | Set an int option on the socket. int zmq_setsockopt (void *s, int option, const 812 | void *optval, size_t optvallen); 813 | 814 | #### func (*Socket) SetSockOptInt64 815 | 816 | ```go 817 | func (s *Socket) SetSockOptInt64(option Int64SocketOption, value int64) error 818 | ``` 819 | Set an int64 option on the socket. int zmq_setsockopt (void *s, int option, 820 | const void *optval, size_t optvallen); 821 | 822 | #### func (*Socket) SetSockOptString 823 | 824 | ```go 825 | func (s *Socket) SetSockOptString(option StringSocketOption, value string) error 826 | ``` 827 | Set a string option on the socket. int zmq_setsockopt (void *s, int option, 828 | const void *optval, size_t optvallen); 829 | 830 | #### func (*Socket) SetSockOptStringNil 831 | 832 | ```go 833 | func (s *Socket) SetSockOptStringNil(option StringSocketOption) error 834 | ``` 835 | Set a string option on the socket to nil. int zmq_setsockopt (void *s, int 836 | option, const void *optval, size_t optvallen); 837 | 838 | #### func (*Socket) SetSockOptUInt64 839 | 840 | ```go 841 | func (s *Socket) SetSockOptUInt64(option UInt64SocketOption, value uint64) error 842 | ``` 843 | Set a uint64 option on the socket. int zmq_setsockopt (void *s, int option, 844 | const void *optval, size_t optvallen); 845 | 846 | #### func (*Socket) SetSubscribe 847 | 848 | ```go 849 | func (s *Socket) SetSubscribe(value string) error 850 | ``` 851 | ZMQ_SUBSCRIBE: Establish message filter. 852 | 853 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc7 854 | 855 | #### func (*Socket) SetSwap 856 | 857 | ```go 858 | func (s *Socket) SetSwap(value int64) error 859 | ``` 860 | ZMQ_SWAP: Set disk offload size. 861 | 862 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc4 863 | 864 | #### func (*Socket) SetTCPKeepalive 865 | 866 | ```go 867 | func (s *Socket) SetTCPKeepalive(value int) error 868 | ``` 869 | ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 870 | 871 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc25 872 | 873 | #### func (*Socket) SetTCPKeepaliveCnt 874 | 875 | ```go 876 | func (s *Socket) SetTCPKeepaliveCnt(value int) error 877 | ``` 878 | ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 879 | 880 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc27 881 | 882 | #### func (*Socket) SetTCPKeepaliveIdle 883 | 884 | ```go 885 | func (s *Socket) SetTCPKeepaliveIdle(value int) error 886 | ``` 887 | ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS). 888 | 889 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc26 890 | 891 | #### func (*Socket) SetTCPKeepaliveIntvl 892 | 893 | ```go 894 | func (s *Socket) SetTCPKeepaliveIntvl(value int) error 895 | ``` 896 | ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 897 | 898 | See: http://api.zeromq.org/3.2:zmq-setsockopt#toc28 899 | 900 | #### func (*Socket) SetUnsubscribe 901 | 902 | ```go 903 | func (s *Socket) SetUnsubscribe(value string) error 904 | ``` 905 | ZMQ_UNSUBSCRIBE: Remove message filter. 906 | 907 | See: http://api.zeromq.org/2.1:zmq-setsockopt#toc8 908 | 909 | #### func (*Socket) SndBuf 910 | 911 | ```go 912 | func (s *Socket) SndBuf() (uint64, error) 913 | ``` 914 | ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 915 | 916 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc13 917 | 918 | #### func (*Socket) SndHWM 919 | 920 | ```go 921 | func (s *Socket) SndHWM() (int, error) 922 | ``` 923 | ZMQ_SNDHWM: Retrieves high water mark for outbound messages. 924 | 925 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc5 926 | 927 | #### func (*Socket) SndTimeout 928 | 929 | ```go 930 | func (s *Socket) SndTimeout() (time.Duration, error) 931 | ``` 932 | ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN. 933 | 934 | See: http://api.zeromq.org/2.2:zmq-getsockopt#toc7 935 | 936 | #### func (*Socket) Swap 937 | 938 | ```go 939 | func (s *Socket) Swap() (int64, error) 940 | ``` 941 | ZMQ_SWAP: Retrieve disk offload size. 942 | 943 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc6 944 | 945 | #### func (*Socket) TCPKeepalive 946 | 947 | ```go 948 | func (s *Socket) TCPKeepalive() (int, error) 949 | ``` 950 | ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 951 | 952 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc26 953 | 954 | #### func (*Socket) TCPKeepaliveCnt 955 | 956 | ```go 957 | func (s *Socket) TCPKeepaliveCnt() (int, error) 958 | ``` 959 | ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 960 | 961 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc28 962 | 963 | #### func (*Socket) TCPKeepaliveIdle 964 | 965 | ```go 966 | func (s *Socket) TCPKeepaliveIdle() (int, error) 967 | ``` 968 | ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS). 969 | 970 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc27 971 | 972 | #### func (*Socket) TCPKeepaliveIntvl 973 | 974 | ```go 975 | func (s *Socket) TCPKeepaliveIntvl() (int, error) 976 | ``` 977 | ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 978 | 979 | See: http://api.zeromq.org/3.2:zmq-getsockopt#toc29 980 | 981 | #### func (*Socket) Type 982 | 983 | ```go 984 | func (s *Socket) Type() (SocketType, error) 985 | ``` 986 | ZMQ_TYPE: Retrieve socket type. 987 | 988 | See: http://api.zeromq.org/2.1:zmq-getsockopt#toc3 989 | 990 | #### type SocketType 991 | 992 | ```go 993 | type SocketType int 994 | ``` 995 | 996 | 997 | #### type StringSocketOption 998 | 999 | ```go 1000 | type StringSocketOption int 1001 | ``` 1002 | 1003 | 1004 | #### type UInt64SocketOption 1005 | 1006 | ```go 1007 | type UInt64SocketOption int 1008 | ``` 1009 | 1010 | 1011 | #### type ZmqOsSocketType 1012 | 1013 | ```go 1014 | type ZmqOsSocketType C.SOCKET 1015 | ``` 1016 | 1017 | 1018 | #### func (ZmqOsSocketType) ToRaw 1019 | 1020 | ```go 1021 | func (self ZmqOsSocketType) ToRaw() C.SOCKET 1022 | ``` 1023 | 1024 | *(generated from .[godocdown](https://github.com/robertkrimen/godocdown).md with `godocdown github.com/alecthomas/gozmq > README.md`)* 1025 | -------------------------------------------------------------------------------- /examples/client/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package main 17 | 18 | import "fmt" 19 | import zmq "github.com/alecthomas/gozmq" 20 | 21 | func main() { 22 | context, _ := zmq.NewContext() 23 | socket, _ := context.NewSocket(zmq.REQ) 24 | socket.Connect("tcp://127.0.0.1:5000") 25 | socket.Connect("tcp://127.0.0.1:6000") 26 | 27 | for i := 0; i < 10; i++ { 28 | msg := fmt.Sprintf("msg %d", i) 29 | socket.Send([]byte(msg), 0) 30 | println("Sending", msg) 31 | socket.Recv(0) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/server/server.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package main 17 | 18 | import zmq "github.com/alecthomas/gozmq" 19 | 20 | func main() { 21 | context, _ := zmq.NewContext() 22 | socket, _ := context.NewSocket(zmq.REP) 23 | socket.Bind("tcp://127.0.0.1:5000") 24 | socket.Bind("tcp://127.0.0.1:6000") 25 | 26 | for { 27 | msg, _ := socket.Recv(0) 28 | println("Got", string(msg)) 29 | socket.Send(msg, 0) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /gozmqfix/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | Copyright (c) 2013 Joshua Tacoma. All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /gozmqfix/README.md: -------------------------------------------------------------------------------- 1 | # gozmqfix 2 | 3 | A `go tool fix` for gozmq projects. 4 | -------------------------------------------------------------------------------- /gozmqfix/fix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | "go/ast" 10 | "go/parser" 11 | "go/token" 12 | "os" 13 | "path" 14 | "reflect" 15 | "strconv" 16 | "strings" 17 | ) 18 | 19 | type fix struct { 20 | name string 21 | date string // date that fix was introduced, in YYYY-MM-DD format 22 | f func(*ast.File) bool 23 | desc string 24 | } 25 | 26 | // main runs sort.Sort(byName(fixes)) before printing list of fixes. 27 | type byName []fix 28 | 29 | func (f byName) Len() int { return len(f) } 30 | func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] } 31 | func (f byName) Less(i, j int) bool { return f[i].name < f[j].name } 32 | 33 | // main runs sort.Sort(byDate(fixes)) before applying fixes. 34 | type byDate []fix 35 | 36 | func (f byDate) Len() int { return len(f) } 37 | func (f byDate) Swap(i, j int) { f[i], f[j] = f[j], f[i] } 38 | func (f byDate) Less(i, j int) bool { return f[i].date < f[j].date } 39 | 40 | var fixes []fix 41 | 42 | func register(f fix) { 43 | fixes = append(fixes, f) 44 | } 45 | 46 | // walk traverses the AST x, calling visit(y) for each node y in the tree but 47 | // also with a pointer to each ast.Expr, ast.Stmt, and *ast.BlockStmt, 48 | // in a bottom-up traversal. 49 | func walk(x interface{}, visit func(interface{})) { 50 | walkBeforeAfter(x, nop, visit) 51 | } 52 | 53 | func nop(interface{}) {} 54 | 55 | // walkBeforeAfter is like walk but calls before(x) before traversing 56 | // x's children and after(x) afterward. 57 | func walkBeforeAfter(x interface{}, before, after func(interface{})) { 58 | before(x) 59 | 60 | switch n := x.(type) { 61 | default: 62 | panic(fmt.Errorf("unexpected type %T in walkBeforeAfter", x)) 63 | 64 | case nil: 65 | 66 | // pointers to interfaces 67 | case *ast.Decl: 68 | walkBeforeAfter(*n, before, after) 69 | case *ast.Expr: 70 | walkBeforeAfter(*n, before, after) 71 | case *ast.Spec: 72 | walkBeforeAfter(*n, before, after) 73 | case *ast.Stmt: 74 | walkBeforeAfter(*n, before, after) 75 | 76 | // pointers to struct pointers 77 | case **ast.BlockStmt: 78 | walkBeforeAfter(*n, before, after) 79 | case **ast.CallExpr: 80 | walkBeforeAfter(*n, before, after) 81 | case **ast.FieldList: 82 | walkBeforeAfter(*n, before, after) 83 | case **ast.FuncType: 84 | walkBeforeAfter(*n, before, after) 85 | case **ast.Ident: 86 | walkBeforeAfter(*n, before, after) 87 | case **ast.BasicLit: 88 | walkBeforeAfter(*n, before, after) 89 | 90 | // pointers to slices 91 | case *[]ast.Decl: 92 | walkBeforeAfter(*n, before, after) 93 | case *[]ast.Expr: 94 | walkBeforeAfter(*n, before, after) 95 | case *[]*ast.File: 96 | walkBeforeAfter(*n, before, after) 97 | case *[]*ast.Ident: 98 | walkBeforeAfter(*n, before, after) 99 | case *[]ast.Spec: 100 | walkBeforeAfter(*n, before, after) 101 | case *[]ast.Stmt: 102 | walkBeforeAfter(*n, before, after) 103 | 104 | // These are ordered and grouped to match ../../pkg/go/ast/ast.go 105 | case *ast.Field: 106 | walkBeforeAfter(&n.Names, before, after) 107 | walkBeforeAfter(&n.Type, before, after) 108 | walkBeforeAfter(&n.Tag, before, after) 109 | case *ast.FieldList: 110 | for _, field := range n.List { 111 | walkBeforeAfter(field, before, after) 112 | } 113 | case *ast.BadExpr: 114 | case *ast.Ident: 115 | case *ast.Ellipsis: 116 | walkBeforeAfter(&n.Elt, before, after) 117 | case *ast.BasicLit: 118 | case *ast.FuncLit: 119 | walkBeforeAfter(&n.Type, before, after) 120 | walkBeforeAfter(&n.Body, before, after) 121 | case *ast.CompositeLit: 122 | walkBeforeAfter(&n.Type, before, after) 123 | walkBeforeAfter(&n.Elts, before, after) 124 | case *ast.ParenExpr: 125 | walkBeforeAfter(&n.X, before, after) 126 | case *ast.SelectorExpr: 127 | walkBeforeAfter(&n.X, before, after) 128 | case *ast.IndexExpr: 129 | walkBeforeAfter(&n.X, before, after) 130 | walkBeforeAfter(&n.Index, before, after) 131 | case *ast.SliceExpr: 132 | walkBeforeAfter(&n.X, before, after) 133 | if n.Low != nil { 134 | walkBeforeAfter(&n.Low, before, after) 135 | } 136 | if n.High != nil { 137 | walkBeforeAfter(&n.High, before, after) 138 | } 139 | case *ast.TypeAssertExpr: 140 | walkBeforeAfter(&n.X, before, after) 141 | walkBeforeAfter(&n.Type, before, after) 142 | case *ast.CallExpr: 143 | walkBeforeAfter(&n.Fun, before, after) 144 | walkBeforeAfter(&n.Args, before, after) 145 | case *ast.StarExpr: 146 | walkBeforeAfter(&n.X, before, after) 147 | case *ast.UnaryExpr: 148 | walkBeforeAfter(&n.X, before, after) 149 | case *ast.BinaryExpr: 150 | walkBeforeAfter(&n.X, before, after) 151 | walkBeforeAfter(&n.Y, before, after) 152 | case *ast.KeyValueExpr: 153 | walkBeforeAfter(&n.Key, before, after) 154 | walkBeforeAfter(&n.Value, before, after) 155 | 156 | case *ast.ArrayType: 157 | walkBeforeAfter(&n.Len, before, after) 158 | walkBeforeAfter(&n.Elt, before, after) 159 | case *ast.StructType: 160 | walkBeforeAfter(&n.Fields, before, after) 161 | case *ast.FuncType: 162 | walkBeforeAfter(&n.Params, before, after) 163 | if n.Results != nil { 164 | walkBeforeAfter(&n.Results, before, after) 165 | } 166 | case *ast.InterfaceType: 167 | walkBeforeAfter(&n.Methods, before, after) 168 | case *ast.MapType: 169 | walkBeforeAfter(&n.Key, before, after) 170 | walkBeforeAfter(&n.Value, before, after) 171 | case *ast.ChanType: 172 | walkBeforeAfter(&n.Value, before, after) 173 | 174 | case *ast.BadStmt: 175 | case *ast.DeclStmt: 176 | walkBeforeAfter(&n.Decl, before, after) 177 | case *ast.EmptyStmt: 178 | case *ast.LabeledStmt: 179 | walkBeforeAfter(&n.Stmt, before, after) 180 | case *ast.ExprStmt: 181 | walkBeforeAfter(&n.X, before, after) 182 | case *ast.SendStmt: 183 | walkBeforeAfter(&n.Chan, before, after) 184 | walkBeforeAfter(&n.Value, before, after) 185 | case *ast.IncDecStmt: 186 | walkBeforeAfter(&n.X, before, after) 187 | case *ast.AssignStmt: 188 | walkBeforeAfter(&n.Lhs, before, after) 189 | walkBeforeAfter(&n.Rhs, before, after) 190 | case *ast.GoStmt: 191 | walkBeforeAfter(&n.Call, before, after) 192 | case *ast.DeferStmt: 193 | walkBeforeAfter(&n.Call, before, after) 194 | case *ast.ReturnStmt: 195 | walkBeforeAfter(&n.Results, before, after) 196 | case *ast.BranchStmt: 197 | case *ast.BlockStmt: 198 | walkBeforeAfter(&n.List, before, after) 199 | case *ast.IfStmt: 200 | walkBeforeAfter(&n.Init, before, after) 201 | walkBeforeAfter(&n.Cond, before, after) 202 | walkBeforeAfter(&n.Body, before, after) 203 | walkBeforeAfter(&n.Else, before, after) 204 | case *ast.CaseClause: 205 | walkBeforeAfter(&n.List, before, after) 206 | walkBeforeAfter(&n.Body, before, after) 207 | case *ast.SwitchStmt: 208 | walkBeforeAfter(&n.Init, before, after) 209 | walkBeforeAfter(&n.Tag, before, after) 210 | walkBeforeAfter(&n.Body, before, after) 211 | case *ast.TypeSwitchStmt: 212 | walkBeforeAfter(&n.Init, before, after) 213 | walkBeforeAfter(&n.Assign, before, after) 214 | walkBeforeAfter(&n.Body, before, after) 215 | case *ast.CommClause: 216 | walkBeforeAfter(&n.Comm, before, after) 217 | walkBeforeAfter(&n.Body, before, after) 218 | case *ast.SelectStmt: 219 | walkBeforeAfter(&n.Body, before, after) 220 | case *ast.ForStmt: 221 | walkBeforeAfter(&n.Init, before, after) 222 | walkBeforeAfter(&n.Cond, before, after) 223 | walkBeforeAfter(&n.Post, before, after) 224 | walkBeforeAfter(&n.Body, before, after) 225 | case *ast.RangeStmt: 226 | walkBeforeAfter(&n.Key, before, after) 227 | walkBeforeAfter(&n.Value, before, after) 228 | walkBeforeAfter(&n.X, before, after) 229 | walkBeforeAfter(&n.Body, before, after) 230 | 231 | case *ast.ImportSpec: 232 | case *ast.ValueSpec: 233 | walkBeforeAfter(&n.Type, before, after) 234 | walkBeforeAfter(&n.Values, before, after) 235 | walkBeforeAfter(&n.Names, before, after) 236 | case *ast.TypeSpec: 237 | walkBeforeAfter(&n.Type, before, after) 238 | 239 | case *ast.BadDecl: 240 | case *ast.GenDecl: 241 | walkBeforeAfter(&n.Specs, before, after) 242 | case *ast.FuncDecl: 243 | if n.Recv != nil { 244 | walkBeforeAfter(&n.Recv, before, after) 245 | } 246 | walkBeforeAfter(&n.Type, before, after) 247 | if n.Body != nil { 248 | walkBeforeAfter(&n.Body, before, after) 249 | } 250 | 251 | case *ast.File: 252 | walkBeforeAfter(&n.Decls, before, after) 253 | 254 | case *ast.Package: 255 | walkBeforeAfter(&n.Files, before, after) 256 | 257 | case []*ast.File: 258 | for i := range n { 259 | walkBeforeAfter(&n[i], before, after) 260 | } 261 | case []ast.Decl: 262 | for i := range n { 263 | walkBeforeAfter(&n[i], before, after) 264 | } 265 | case []ast.Expr: 266 | for i := range n { 267 | walkBeforeAfter(&n[i], before, after) 268 | } 269 | case []*ast.Ident: 270 | for i := range n { 271 | walkBeforeAfter(&n[i], before, after) 272 | } 273 | case []ast.Stmt: 274 | for i := range n { 275 | walkBeforeAfter(&n[i], before, after) 276 | } 277 | case []ast.Spec: 278 | for i := range n { 279 | walkBeforeAfter(&n[i], before, after) 280 | } 281 | } 282 | after(x) 283 | } 284 | 285 | // imports returns true if f imports path. 286 | func imports(f *ast.File, path string) bool { 287 | return importSpec(f, path) != nil 288 | } 289 | 290 | // importSpec returns the import spec if f imports path, 291 | // or nil otherwise. 292 | func importSpec(f *ast.File, path string) *ast.ImportSpec { 293 | for _, s := range f.Imports { 294 | if importPath(s) == path { 295 | return s 296 | } 297 | } 298 | return nil 299 | } 300 | 301 | // importPath returns the unquoted import path of s, 302 | // or "" if the path is not properly quoted. 303 | func importPath(s *ast.ImportSpec) string { 304 | t, err := strconv.Unquote(s.Path.Value) 305 | if err == nil { 306 | return t 307 | } 308 | return "" 309 | } 310 | 311 | // declImports reports whether gen contains an import of path. 312 | func declImports(gen *ast.GenDecl, path string) bool { 313 | if gen.Tok != token.IMPORT { 314 | return false 315 | } 316 | for _, spec := range gen.Specs { 317 | impspec := spec.(*ast.ImportSpec) 318 | if importPath(impspec) == path { 319 | return true 320 | } 321 | } 322 | return false 323 | } 324 | 325 | // isPkgDot returns true if t is the expression "pkg.name" 326 | // where pkg is an imported identifier. 327 | func isPkgDot(t ast.Expr, pkg, name string) bool { 328 | sel, ok := t.(*ast.SelectorExpr) 329 | return ok && isTopName(sel.X, pkg) && sel.Sel.String() == name 330 | } 331 | 332 | // isPtrPkgDot returns true if f is the expression "*pkg.name" 333 | // where pkg is an imported identifier. 334 | func isPtrPkgDot(t ast.Expr, pkg, name string) bool { 335 | ptr, ok := t.(*ast.StarExpr) 336 | return ok && isPkgDot(ptr.X, pkg, name) 337 | } 338 | 339 | // isTopName returns true if n is a top-level unresolved identifier with the given name. 340 | func isTopName(n ast.Expr, name string) bool { 341 | id, ok := n.(*ast.Ident) 342 | return ok && id.Name == name && id.Obj == nil 343 | } 344 | 345 | // isName returns true if n is an identifier with the given name. 346 | func isName(n ast.Expr, name string) bool { 347 | id, ok := n.(*ast.Ident) 348 | return ok && id.String() == name 349 | } 350 | 351 | // isCall returns true if t is a call to pkg.name. 352 | func isCall(t ast.Expr, pkg, name string) bool { 353 | call, ok := t.(*ast.CallExpr) 354 | return ok && isPkgDot(call.Fun, pkg, name) 355 | } 356 | 357 | // If n is an *ast.Ident, isIdent returns it; otherwise isIdent returns nil. 358 | func isIdent(n interface{}) *ast.Ident { 359 | id, _ := n.(*ast.Ident) 360 | return id 361 | } 362 | 363 | // refersTo returns true if n is a reference to the same object as x. 364 | func refersTo(n ast.Node, x *ast.Ident) bool { 365 | id, ok := n.(*ast.Ident) 366 | // The test of id.Name == x.Name handles top-level unresolved 367 | // identifiers, which all have Obj == nil. 368 | return ok && id.Obj == x.Obj && id.Name == x.Name 369 | } 370 | 371 | // isBlank returns true if n is the blank identifier. 372 | func isBlank(n ast.Expr) bool { 373 | return isName(n, "_") 374 | } 375 | 376 | // isEmptyString returns true if n is an empty string literal. 377 | func isEmptyString(n ast.Expr) bool { 378 | lit, ok := n.(*ast.BasicLit) 379 | return ok && lit.Kind == token.STRING && len(lit.Value) == 2 380 | } 381 | 382 | func warn(pos token.Pos, msg string, args ...interface{}) { 383 | if pos.IsValid() { 384 | msg = "%s: " + msg 385 | arg1 := []interface{}{fset.Position(pos).String()} 386 | args = append(arg1, args...) 387 | } 388 | fmt.Fprintf(os.Stderr, msg+"\n", args...) 389 | } 390 | 391 | // countUses returns the number of uses of the identifier x in scope. 392 | func countUses(x *ast.Ident, scope []ast.Stmt) int { 393 | count := 0 394 | ff := func(n interface{}) { 395 | if n, ok := n.(ast.Node); ok && refersTo(n, x) { 396 | count++ 397 | } 398 | } 399 | for _, n := range scope { 400 | walk(n, ff) 401 | } 402 | return count 403 | } 404 | 405 | // rewriteUses replaces all uses of the identifier x and !x in scope 406 | // with f(x.Pos()) and fnot(x.Pos()). 407 | func rewriteUses(x *ast.Ident, f, fnot func(token.Pos) ast.Expr, scope []ast.Stmt) { 408 | var lastF ast.Expr 409 | ff := func(n interface{}) { 410 | ptr, ok := n.(*ast.Expr) 411 | if !ok { 412 | return 413 | } 414 | nn := *ptr 415 | 416 | // The child node was just walked and possibly replaced. 417 | // If it was replaced and this is a negation, replace with fnot(p). 418 | not, ok := nn.(*ast.UnaryExpr) 419 | if ok && not.Op == token.NOT && not.X == lastF { 420 | *ptr = fnot(nn.Pos()) 421 | return 422 | } 423 | if refersTo(nn, x) { 424 | lastF = f(nn.Pos()) 425 | *ptr = lastF 426 | } 427 | } 428 | for _, n := range scope { 429 | walk(n, ff) 430 | } 431 | } 432 | 433 | // assignsTo returns true if any of the code in scope assigns to or takes the address of x. 434 | func assignsTo(x *ast.Ident, scope []ast.Stmt) bool { 435 | assigned := false 436 | ff := func(n interface{}) { 437 | if assigned { 438 | return 439 | } 440 | switch n := n.(type) { 441 | case *ast.UnaryExpr: 442 | // use of &x 443 | if n.Op == token.AND && refersTo(n.X, x) { 444 | assigned = true 445 | return 446 | } 447 | case *ast.AssignStmt: 448 | for _, l := range n.Lhs { 449 | if refersTo(l, x) { 450 | assigned = true 451 | return 452 | } 453 | } 454 | } 455 | } 456 | for _, n := range scope { 457 | if assigned { 458 | break 459 | } 460 | walk(n, ff) 461 | } 462 | return assigned 463 | } 464 | 465 | // newPkgDot returns an ast.Expr referring to "pkg.name" at position pos. 466 | func newPkgDot(pos token.Pos, pkg, name string) ast.Expr { 467 | return &ast.SelectorExpr{ 468 | X: &ast.Ident{ 469 | NamePos: pos, 470 | Name: pkg, 471 | }, 472 | Sel: &ast.Ident{ 473 | NamePos: pos, 474 | Name: name, 475 | }, 476 | } 477 | } 478 | 479 | // renameTop renames all references to the top-level name old. 480 | // It returns true if it makes any changes. 481 | func renameTop(f *ast.File, old, new string) bool { 482 | var fixed bool 483 | 484 | // Rename any conflicting imports 485 | // (assuming package name is last element of path). 486 | for _, s := range f.Imports { 487 | if s.Name != nil { 488 | if s.Name.Name == old { 489 | s.Name.Name = new 490 | fixed = true 491 | } 492 | } else { 493 | _, thisName := path.Split(importPath(s)) 494 | if thisName == old { 495 | s.Name = ast.NewIdent(new) 496 | fixed = true 497 | } 498 | } 499 | } 500 | 501 | // Rename any top-level declarations. 502 | for _, d := range f.Decls { 503 | switch d := d.(type) { 504 | case *ast.FuncDecl: 505 | if d.Recv == nil && d.Name.Name == old { 506 | d.Name.Name = new 507 | d.Name.Obj.Name = new 508 | fixed = true 509 | } 510 | case *ast.GenDecl: 511 | for _, s := range d.Specs { 512 | switch s := s.(type) { 513 | case *ast.TypeSpec: 514 | if s.Name.Name == old { 515 | s.Name.Name = new 516 | s.Name.Obj.Name = new 517 | fixed = true 518 | } 519 | case *ast.ValueSpec: 520 | for _, n := range s.Names { 521 | if n.Name == old { 522 | n.Name = new 523 | n.Obj.Name = new 524 | fixed = true 525 | } 526 | } 527 | } 528 | } 529 | } 530 | } 531 | 532 | // Rename top-level old to new, both unresolved names 533 | // (probably defined in another file) and names that resolve 534 | // to a declaration we renamed. 535 | walk(f, func(n interface{}) { 536 | id, ok := n.(*ast.Ident) 537 | if ok && isTopName(id, old) { 538 | id.Name = new 539 | fixed = true 540 | } 541 | if ok && id.Obj != nil && id.Name == old && id.Obj.Name == new { 542 | id.Name = id.Obj.Name 543 | fixed = true 544 | } 545 | }) 546 | 547 | return fixed 548 | } 549 | 550 | // matchLen returns the length of the longest prefix shared by x and y. 551 | func matchLen(x, y string) int { 552 | i := 0 553 | for i < len(x) && i < len(y) && x[i] == y[i] { 554 | i++ 555 | } 556 | return i 557 | } 558 | 559 | // addImport adds the import path to the file f, if absent. 560 | func addImport(f *ast.File, ipath string) (added bool) { 561 | if imports(f, ipath) { 562 | return false 563 | } 564 | 565 | // Determine name of import. 566 | // Assume added imports follow convention of using last element. 567 | _, name := path.Split(ipath) 568 | 569 | // Rename any conflicting top-level references from name to name_. 570 | renameTop(f, name, name+"_") 571 | 572 | newImport := &ast.ImportSpec{ 573 | Path: &ast.BasicLit{ 574 | Kind: token.STRING, 575 | Value: strconv.Quote(ipath), 576 | }, 577 | } 578 | 579 | // Find an import decl to add to. 580 | var ( 581 | bestMatch = -1 582 | lastImport = -1 583 | impDecl *ast.GenDecl 584 | impIndex = -1 585 | ) 586 | for i, decl := range f.Decls { 587 | gen, ok := decl.(*ast.GenDecl) 588 | if ok && gen.Tok == token.IMPORT { 589 | lastImport = i 590 | // Do not add to import "C", to avoid disrupting the 591 | // association with its doc comment, breaking cgo. 592 | if declImports(gen, "C") { 593 | continue 594 | } 595 | 596 | // Compute longest shared prefix with imports in this block. 597 | for j, spec := range gen.Specs { 598 | impspec := spec.(*ast.ImportSpec) 599 | n := matchLen(importPath(impspec), ipath) 600 | if n > bestMatch { 601 | bestMatch = n 602 | impDecl = gen 603 | impIndex = j 604 | } 605 | } 606 | } 607 | } 608 | 609 | // If no import decl found, add one after the last import. 610 | if impDecl == nil { 611 | impDecl = &ast.GenDecl{ 612 | Tok: token.IMPORT, 613 | } 614 | f.Decls = append(f.Decls, nil) 615 | copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) 616 | f.Decls[lastImport+1] = impDecl 617 | } 618 | 619 | // Ensure the import decl has parentheses, if needed. 620 | if len(impDecl.Specs) > 0 && !impDecl.Lparen.IsValid() { 621 | impDecl.Lparen = impDecl.Pos() 622 | } 623 | 624 | insertAt := impIndex + 1 625 | if insertAt == 0 { 626 | insertAt = len(impDecl.Specs) 627 | } 628 | impDecl.Specs = append(impDecl.Specs, nil) 629 | copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) 630 | impDecl.Specs[insertAt] = newImport 631 | if insertAt > 0 { 632 | // Assign same position as the previous import, 633 | // so that the sorter sees it as being in the same block. 634 | prev := impDecl.Specs[insertAt-1] 635 | newImport.Path.ValuePos = prev.Pos() 636 | newImport.EndPos = prev.Pos() 637 | } 638 | 639 | f.Imports = append(f.Imports, newImport) 640 | return true 641 | } 642 | 643 | // deleteImport deletes the import path from the file f, if present. 644 | func deleteImport(f *ast.File, path string) (deleted bool) { 645 | oldImport := importSpec(f, path) 646 | 647 | // Find the import node that imports path, if any. 648 | for i, decl := range f.Decls { 649 | gen, ok := decl.(*ast.GenDecl) 650 | if !ok || gen.Tok != token.IMPORT { 651 | continue 652 | } 653 | for j, spec := range gen.Specs { 654 | impspec := spec.(*ast.ImportSpec) 655 | if oldImport != impspec { 656 | continue 657 | } 658 | 659 | // We found an import spec that imports path. 660 | // Delete it. 661 | deleted = true 662 | copy(gen.Specs[j:], gen.Specs[j+1:]) 663 | gen.Specs = gen.Specs[:len(gen.Specs)-1] 664 | 665 | // If this was the last import spec in this decl, 666 | // delete the decl, too. 667 | if len(gen.Specs) == 0 { 668 | copy(f.Decls[i:], f.Decls[i+1:]) 669 | f.Decls = f.Decls[:len(f.Decls)-1] 670 | } else if len(gen.Specs) == 1 { 671 | gen.Lparen = token.NoPos // drop parens 672 | } 673 | if j > 0 { 674 | // We deleted an entry but now there will be 675 | // a blank line-sized hole where the import was. 676 | // Close the hole by making the previous 677 | // import appear to "end" where this one did. 678 | gen.Specs[j-1].(*ast.ImportSpec).EndPos = impspec.End() 679 | } 680 | break 681 | } 682 | } 683 | 684 | // Delete it from f.Imports. 685 | for i, imp := range f.Imports { 686 | if imp == oldImport { 687 | copy(f.Imports[i:], f.Imports[i+1:]) 688 | f.Imports = f.Imports[:len(f.Imports)-1] 689 | break 690 | } 691 | } 692 | 693 | return 694 | } 695 | 696 | // rewriteImport rewrites any import of path oldPath to path newPath. 697 | func rewriteImport(f *ast.File, oldPath, newPath string) (rewrote bool) { 698 | for _, imp := range f.Imports { 699 | if importPath(imp) == oldPath { 700 | rewrote = true 701 | // record old End, because the default is to compute 702 | // it using the length of imp.Path.Value. 703 | imp.EndPos = imp.End() 704 | imp.Path.Value = strconv.Quote(newPath) 705 | } 706 | } 707 | return 708 | } 709 | 710 | func usesImport(f *ast.File, path string) (used bool) { 711 | spec := importSpec(f, path) 712 | if spec == nil { 713 | return 714 | } 715 | 716 | name := spec.Name.String() 717 | switch name { 718 | case "": 719 | // If the package name is not explicitly specified, 720 | // make an educated guess. This is not guaranteed to be correct. 721 | lastSlash := strings.LastIndex(path, "/") 722 | if lastSlash == -1 { 723 | name = path 724 | } else { 725 | name = path[lastSlash+1:] 726 | } 727 | case "_", ".": 728 | // Not sure if this import is used - err on the side of caution. 729 | return true 730 | } 731 | 732 | walk(f, func(n interface{}) { 733 | sel, ok := n.(*ast.SelectorExpr) 734 | if ok && isTopName(sel.X, name) { 735 | used = true 736 | } 737 | }) 738 | 739 | return 740 | } 741 | 742 | func expr(s string) ast.Expr { 743 | x, err := parser.ParseExpr(s) 744 | if err != nil { 745 | panic("parsing " + s + ": " + err.Error()) 746 | } 747 | // Remove position information to avoid spurious newlines. 748 | killPos(reflect.ValueOf(x)) 749 | return x 750 | } 751 | 752 | var posType = reflect.TypeOf(token.Pos(0)) 753 | 754 | func killPos(v reflect.Value) { 755 | switch v.Kind() { 756 | case reflect.Ptr, reflect.Interface: 757 | if !v.IsNil() { 758 | killPos(v.Elem()) 759 | } 760 | case reflect.Slice: 761 | n := v.Len() 762 | for i := 0; i < n; i++ { 763 | killPos(v.Index(i)) 764 | } 765 | case reflect.Struct: 766 | n := v.NumField() 767 | for i := 0; i < n; i++ { 768 | f := v.Field(i) 769 | if f.Type() == posType { 770 | f.SetInt(0) 771 | continue 772 | } 773 | killPos(f) 774 | } 775 | } 776 | } 777 | 778 | // A Rename describes a single renaming. 779 | type rename struct { 780 | OldImport string // only apply rename if this import is present 781 | NewImport string // add this import during rewrite 782 | Old string // old name: p.T or *p.T 783 | New string // new name: p.T or *p.T 784 | } 785 | 786 | func renameFix(tab []rename) func(*ast.File) bool { 787 | return func(f *ast.File) bool { 788 | return renameFixTab(f, tab) 789 | } 790 | } 791 | 792 | func parseName(s string) (ptr bool, pkg, nam string) { 793 | i := strings.Index(s, ".") 794 | if i < 0 { 795 | panic("parseName: invalid name " + s) 796 | } 797 | if strings.HasPrefix(s, "*") { 798 | ptr = true 799 | s = s[1:] 800 | i-- 801 | } 802 | pkg = s[:i] 803 | nam = s[i+1:] 804 | return 805 | } 806 | 807 | func renameFixTab(f *ast.File, tab []rename) bool { 808 | fixed := false 809 | added := map[string]bool{} 810 | check := map[string]bool{} 811 | for _, t := range tab { 812 | if !imports(f, t.OldImport) { 813 | continue 814 | } 815 | optr, opkg, onam := parseName(t.Old) 816 | walk(f, func(n interface{}) { 817 | np, ok := n.(*ast.Expr) 818 | if !ok { 819 | return 820 | } 821 | x := *np 822 | if optr { 823 | p, ok := x.(*ast.StarExpr) 824 | if !ok { 825 | return 826 | } 827 | x = p.X 828 | } 829 | if !isPkgDot(x, opkg, onam) { 830 | return 831 | } 832 | if t.NewImport != "" && !added[t.NewImport] { 833 | addImport(f, t.NewImport) 834 | added[t.NewImport] = true 835 | } 836 | *np = expr(t.New) 837 | check[t.OldImport] = true 838 | fixed = true 839 | }) 840 | } 841 | 842 | for ipath := range check { 843 | if !usesImport(f, ipath) { 844 | deleteImport(f, ipath) 845 | } 846 | } 847 | return fixed 848 | } 849 | -------------------------------------------------------------------------------- /gozmqfix/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "bytes" 9 | "flag" 10 | "fmt" 11 | "go/ast" 12 | "go/parser" 13 | "go/printer" 14 | "go/scanner" 15 | "go/token" 16 | "io/ioutil" 17 | "os" 18 | "os/exec" 19 | "path/filepath" 20 | "sort" 21 | "strings" 22 | ) 23 | 24 | var ( 25 | fset = token.NewFileSet() 26 | exitCode = 0 27 | ) 28 | 29 | var allowedRewrites = flag.String("r", "", 30 | "restrict the rewrites to this comma-separated list") 31 | 32 | var forceRewrites = flag.String("force", "", 33 | "force these fixes to run even if the code looks updated") 34 | 35 | var allowed, force map[string]bool 36 | 37 | var doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files") 38 | 39 | // enable for debugging fix failures 40 | const debug = false // display incorrectly reformatted source and exit 41 | 42 | func usage() { 43 | fmt.Fprintf(os.Stderr, "usage: go tool fix [-diff] [-r fixname,...] [-force fixname,...] [path ...]\n") 44 | flag.PrintDefaults() 45 | fmt.Fprintf(os.Stderr, "\nAvailable rewrites are:\n") 46 | sort.Sort(byName(fixes)) 47 | for _, f := range fixes { 48 | fmt.Fprintf(os.Stderr, "\n%s\n", f.name) 49 | desc := strings.TrimSpace(f.desc) 50 | desc = strings.Replace(desc, "\n", "\n\t", -1) 51 | fmt.Fprintf(os.Stderr, "\t%s\n", desc) 52 | } 53 | os.Exit(2) 54 | } 55 | 56 | func main() { 57 | flag.Usage = usage 58 | flag.Parse() 59 | 60 | sort.Sort(byDate(fixes)) 61 | 62 | if *allowedRewrites != "" { 63 | allowed = make(map[string]bool) 64 | for _, f := range strings.Split(*allowedRewrites, ",") { 65 | allowed[f] = true 66 | } 67 | } 68 | 69 | if *forceRewrites != "" { 70 | force = make(map[string]bool) 71 | for _, f := range strings.Split(*forceRewrites, ",") { 72 | force[f] = true 73 | } 74 | } 75 | 76 | if flag.NArg() == 0 { 77 | if err := processFile("standard input", true); err != nil { 78 | report(err) 79 | } 80 | os.Exit(exitCode) 81 | } 82 | 83 | for i := 0; i < flag.NArg(); i++ { 84 | path := flag.Arg(i) 85 | switch dir, err := os.Stat(path); { 86 | case err != nil: 87 | report(err) 88 | case dir.IsDir(): 89 | walkDir(path) 90 | default: 91 | if err := processFile(path, false); err != nil { 92 | report(err) 93 | } 94 | } 95 | } 96 | 97 | os.Exit(exitCode) 98 | } 99 | 100 | const ( 101 | tabWidth = 8 102 | parserMode = parser.ParseComments 103 | printerMode = printer.TabIndent | printer.UseSpaces 104 | ) 105 | 106 | var printConfig = &printer.Config{ 107 | Mode: printerMode, 108 | Tabwidth: tabWidth, 109 | } 110 | 111 | func gofmtFile(f *ast.File) ([]byte, error) { 112 | var buf bytes.Buffer 113 | 114 | ast.SortImports(fset, f) 115 | err := printConfig.Fprint(&buf, fset, f) 116 | if err != nil { 117 | return nil, err 118 | } 119 | return buf.Bytes(), nil 120 | } 121 | 122 | func processFile(filename string, useStdin bool) error { 123 | var f *os.File 124 | var err error 125 | var fixlog bytes.Buffer 126 | 127 | if useStdin { 128 | f = os.Stdin 129 | } else { 130 | f, err = os.Open(filename) 131 | if err != nil { 132 | return err 133 | } 134 | defer f.Close() 135 | } 136 | 137 | src, err := ioutil.ReadAll(f) 138 | if err != nil { 139 | return err 140 | } 141 | 142 | file, err := parser.ParseFile(fset, filename, src, parserMode) 143 | if err != nil { 144 | return err 145 | } 146 | 147 | // Apply all fixes to file. 148 | newFile := file 149 | fixed := false 150 | for _, fix := range fixes { 151 | if allowed != nil && !allowed[fix.name] { 152 | continue 153 | } 154 | if fix.f(newFile) { 155 | fixed = true 156 | fmt.Fprintf(&fixlog, " %s", fix.name) 157 | 158 | // AST changed. 159 | // Print and parse, to update any missing scoping 160 | // or position information for subsequent fixers. 161 | newSrc, err := gofmtFile(newFile) 162 | if err != nil { 163 | return err 164 | } 165 | newFile, err = parser.ParseFile(fset, filename, newSrc, parserMode) 166 | if err != nil { 167 | if debug { 168 | fmt.Printf("%s", newSrc) 169 | report(err) 170 | os.Exit(exitCode) 171 | } 172 | return err 173 | } 174 | } 175 | } 176 | if !fixed { 177 | return nil 178 | } 179 | fmt.Fprintf(os.Stderr, "%s: fixed %s\n", filename, fixlog.String()[1:]) 180 | 181 | // Print AST. We did that after each fix, so this appears 182 | // redundant, but it is necessary to generate gofmt-compatible 183 | // source code in a few cases. The official gofmt style is the 184 | // output of the printer run on a standard AST generated by the parser, 185 | // but the source we generated inside the loop above is the 186 | // output of the printer run on a mangled AST generated by a fixer. 187 | newSrc, err := gofmtFile(newFile) 188 | if err != nil { 189 | return err 190 | } 191 | 192 | if *doDiff { 193 | data, err := diff(src, newSrc) 194 | if err != nil { 195 | return fmt.Errorf("computing diff: %s", err) 196 | } 197 | fmt.Printf("diff %s fixed/%s\n", filename, filename) 198 | os.Stdout.Write(data) 199 | return nil 200 | } 201 | 202 | if useStdin { 203 | os.Stdout.Write(newSrc) 204 | return nil 205 | } 206 | 207 | return ioutil.WriteFile(f.Name(), newSrc, 0) 208 | } 209 | 210 | var gofmtBuf bytes.Buffer 211 | 212 | func gofmt(n interface{}) string { 213 | gofmtBuf.Reset() 214 | err := printConfig.Fprint(&gofmtBuf, fset, n) 215 | if err != nil { 216 | return "<" + err.Error() + ">" 217 | } 218 | return gofmtBuf.String() 219 | } 220 | 221 | func report(err error) { 222 | scanner.PrintError(os.Stderr, err) 223 | exitCode = 2 224 | } 225 | 226 | func walkDir(path string) { 227 | filepath.Walk(path, visitFile) 228 | } 229 | 230 | func visitFile(path string, f os.FileInfo, err error) error { 231 | if err == nil && isGoFile(f) { 232 | err = processFile(path, false) 233 | } 234 | if err != nil { 235 | report(err) 236 | } 237 | return nil 238 | } 239 | 240 | func isGoFile(f os.FileInfo) bool { 241 | // ignore non-Go files 242 | name := f.Name() 243 | return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") 244 | } 245 | 246 | func diff(b1, b2 []byte) (data []byte, err error) { 247 | f1, err := ioutil.TempFile("", "go-fix") 248 | if err != nil { 249 | return nil, err 250 | } 251 | defer os.Remove(f1.Name()) 252 | defer f1.Close() 253 | 254 | f2, err := ioutil.TempFile("", "go-fix") 255 | if err != nil { 256 | return nil, err 257 | } 258 | defer os.Remove(f2.Name()) 259 | defer f2.Close() 260 | 261 | f1.Write(b1) 262 | f2.Write(b2) 263 | 264 | data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput() 265 | if len(data) > 0 { 266 | // diff exits with a non-zero status when the files don't match. 267 | // Ignore that failure as long as we get output. 268 | err = nil 269 | } 270 | return 271 | } 272 | -------------------------------------------------------------------------------- /gozmqfix/main_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "go/ast" 9 | "go/parser" 10 | "strings" 11 | "testing" 12 | ) 13 | 14 | type testCase struct { 15 | Name string 16 | Fn func(*ast.File) bool 17 | In string 18 | Out string 19 | } 20 | 21 | var testCases []testCase 22 | 23 | func addTestCases(t []testCase, fn func(*ast.File) bool) { 24 | // Fill in fn to avoid repetition in definitions. 25 | if fn != nil { 26 | for i := range t { 27 | if t[i].Fn == nil { 28 | t[i].Fn = fn 29 | } 30 | } 31 | } 32 | testCases = append(testCases, t...) 33 | } 34 | 35 | func fnop(*ast.File) bool { return false } 36 | 37 | func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string, mustBeGofmt bool) (out string, fixed, ok bool) { 38 | file, err := parser.ParseFile(fset, desc, in, parserMode) 39 | if err != nil { 40 | t.Errorf("%s: parsing: %v", desc, err) 41 | return 42 | } 43 | 44 | outb, err := gofmtFile(file) 45 | if err != nil { 46 | t.Errorf("%s: printing: %v", desc, err) 47 | return 48 | } 49 | if s := string(outb); in != s && mustBeGofmt { 50 | t.Errorf("%s: not gofmt-formatted.\n--- %s\n%s\n--- %s | gofmt\n%s", 51 | desc, desc, in, desc, s) 52 | tdiff(t, in, s) 53 | return 54 | } 55 | 56 | if fn == nil { 57 | for _, fix := range fixes { 58 | if fix.f(file) { 59 | fixed = true 60 | } 61 | } 62 | } else { 63 | fixed = fn(file) 64 | } 65 | 66 | outb, err = gofmtFile(file) 67 | if err != nil { 68 | t.Errorf("%s: printing: %v", desc, err) 69 | return 70 | } 71 | 72 | return string(outb), fixed, true 73 | } 74 | 75 | func TestRewrite(t *testing.T) { 76 | for _, tt := range testCases { 77 | // Apply fix: should get tt.Out. 78 | out, fixed, ok := parseFixPrint(t, tt.Fn, tt.Name, tt.In, true) 79 | if !ok { 80 | continue 81 | } 82 | 83 | // reformat to get printing right 84 | out, _, ok = parseFixPrint(t, fnop, tt.Name, out, false) 85 | if !ok { 86 | continue 87 | } 88 | 89 | if out != tt.Out { 90 | t.Errorf("%s: incorrect output.\n", tt.Name) 91 | if !strings.HasPrefix(tt.Name, "testdata/") { 92 | t.Errorf("--- have\n%s\n--- want\n%s", out, tt.Out) 93 | } 94 | tdiff(t, out, tt.Out) 95 | continue 96 | } 97 | 98 | if changed := out != tt.In; changed != fixed { 99 | t.Errorf("%s: changed=%v != fixed=%v", tt.Name, changed, fixed) 100 | continue 101 | } 102 | 103 | // Should not change if run again. 104 | out2, fixed2, ok := parseFixPrint(t, tt.Fn, tt.Name+" output", out, true) 105 | if !ok { 106 | continue 107 | } 108 | 109 | if fixed2 { 110 | t.Errorf("%s: applied fixes during second round", tt.Name) 111 | continue 112 | } 113 | 114 | if out2 != out { 115 | t.Errorf("%s: changed output after second round of fixes.\n--- output after first round\n%s\n--- output after second round\n%s", 116 | tt.Name, out, out2) 117 | tdiff(t, out, out2) 118 | } 119 | } 120 | } 121 | 122 | func tdiff(t *testing.T, a, b string) { 123 | data, err := diff([]byte(a), []byte(b)) 124 | if err != nil { 125 | t.Error(err) 126 | return 127 | } 128 | t.Error(string(data)) 129 | } 130 | -------------------------------------------------------------------------------- /gozmqfix/zmqstruct.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Joshua Tacoma. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "go/ast" 9 | ) 10 | 11 | func init() { 12 | register(zmqstructFix) 13 | } 14 | 15 | var zmqstructFix = fix{ 16 | "zmqstruct", 17 | "2013-03-20", 18 | zmqstruct, 19 | ` 20 | Make github.com/alecthomas/gozmq use structs instead of interfaces. 21 | `, 22 | } 23 | 24 | func zmqstruct(f *ast.File) bool { 25 | spec := importSpec(f, "github.com/alecthomas/gozmq") 26 | if spec == nil { 27 | return false 28 | } 29 | zmq := "gozmq" 30 | if spec.Name != nil { 31 | zmq = spec.Name.Name 32 | } 33 | 34 | fixed := false 35 | walk(f, func(n interface{}) { 36 | switch node := n.(type) { 37 | case *ast.ArrayType: 38 | t := zmqstructtype(zmq, node.Elt) 39 | if t != nil { 40 | node.Elt = t 41 | fixed = true 42 | } 43 | case *ast.CompositeLit: 44 | // This is irrelevant only because the original type is an 45 | // interface i.e. cannot be the type of a composite literal. 46 | case *ast.Ellipsis: 47 | t := zmqstructtype(zmq, node.Elt) 48 | if t != nil { 49 | node.Elt = t 50 | fixed = true 51 | } 52 | case *ast.Field: 53 | t := zmqstructtype(zmq, node.Type) 54 | if t != nil { 55 | node.Type = t 56 | fixed = true 57 | } 58 | case *ast.MapType: 59 | t := zmqstructtype(zmq, node.Key) 60 | if t != nil { 61 | node.Key = t 62 | fixed = true 63 | } 64 | t = zmqstructtype(zmq, node.Value) 65 | if t != nil { 66 | node.Value = t 67 | fixed = true 68 | } 69 | case *ast.Object: 70 | // Does something need to be done here with node.Type? 71 | // What does it take to trigger this case? 72 | case *ast.TypeAssertExpr: 73 | t := zmqstructtype(zmq, node.Type) 74 | if t != nil { 75 | node.Type = t 76 | fixed = true 77 | } 78 | case *ast.TypeSpec: 79 | t := zmqstructtype(zmq, node.Type) 80 | if t != nil { 81 | node.Type = t 82 | fixed = true 83 | } 84 | case *ast.ValueSpec: 85 | t := zmqstructtype(zmq, node.Type) 86 | if t != nil { 87 | node.Type = t 88 | fixed = true 89 | } 90 | } 91 | }) 92 | return fixed 93 | } 94 | 95 | func zmqstructtype(zmq string, n ast.Expr) ast.Expr { 96 | s, ok := n.(*ast.SelectorExpr) 97 | if ok { 98 | p, ok := s.X.(*ast.Ident) 99 | if ok && p.Name == zmq { 100 | if s.Sel.Name == "Context" || s.Sel.Name == "Socket" { 101 | return &ast.StarExpr{ 102 | X: &ast.SelectorExpr{ 103 | X: ast.NewIdent(zmq), 104 | Sel: ast.NewIdent(s.Sel.Name), 105 | }, 106 | } 107 | } 108 | } 109 | } 110 | return nil 111 | } 112 | -------------------------------------------------------------------------------- /gozmqfix/zmqstruct_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Joshua Tacoma. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | func init() { 8 | addTestCases(zmqstructTests, zmqstruct) 9 | } 10 | 11 | var zmqstructTests = []testCase{ 12 | { 13 | Name: "zmqstruct.0", 14 | In: `package main 15 | 16 | import zmq "github.com/alecthomas/gozmq" 17 | 18 | type M struct { 19 | c zmq.Context 20 | s zmq.Socket 21 | ss []zmq.Socket 22 | m map[zmq.Context]zmq.Socket 23 | } 24 | 25 | type S0 zmq.Socket 26 | 27 | func newM(c zmq.Context, s zmq.Socket, ss ...zmq.Socket) *M { 28 | if s == nil { 29 | s = c.NewSocket(zmq.PUB) 30 | } 31 | return &M{ 32 | c: c, 33 | s: s, 34 | ss: ss, 35 | } 36 | } 37 | 38 | var GlobalM = newM(c.NewContext(), nil.(zmq.Socket)) 39 | 40 | type Socket zmq.Socket 41 | 42 | var S Socket = Socket(M.s) 43 | `, 44 | Out: `package main 45 | 46 | import zmq "github.com/alecthomas/gozmq" 47 | 48 | type M struct { 49 | c *zmq.Context 50 | s *zmq.Socket 51 | ss []*zmq.Socket 52 | m map[*zmq.Context]*zmq.Socket 53 | } 54 | 55 | type S0 *zmq.Socket 56 | 57 | func newM(c *zmq.Context, s *zmq.Socket, ss ...*zmq.Socket) *M { 58 | if s == nil { 59 | s = c.NewSocket(zmq.PUB) 60 | } 61 | return &M{ 62 | c: c, 63 | s: s, 64 | ss: ss, 65 | } 66 | } 67 | 68 | var GlobalM = newM(c.NewContext(), nil.(*zmq.Socket)) 69 | 70 | type Socket *zmq.Socket 71 | 72 | var S Socket = Socket(M.s) 73 | `, 74 | }, 75 | { 76 | Name: "zmqstruct.1", 77 | In: `package main 78 | 79 | import "github.com/alecthomas/gozmq" 80 | 81 | type Socket *gozmq.Socket 82 | `, 83 | Out: `package main 84 | 85 | import "github.com/alecthomas/gozmq" 86 | 87 | type Socket *gozmq.Socket 88 | `, 89 | }, 90 | } 91 | -------------------------------------------------------------------------------- /gozmqgen/README.md: -------------------------------------------------------------------------------- 1 | # gozmqgen 2 | 3 | Intended use is: 4 | 5 | cd gozmq 6 | go run ./gozmqgen/main.go 7 | 8 | In case the template isn't quite right, you should also: 9 | 10 | go fmt *.go 11 | 12 | -------------------------------------------------------------------------------- /gozmqgen/header.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alecthomas/gozmq/d1b01a2df6b2c64f03fecaeabea541963fc4749f/gozmqgen/header.txt -------------------------------------------------------------------------------- /gozmqgen/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/xml" 5 | "flag" 6 | "fmt" 7 | "io" 8 | "io/ioutil" 9 | "net/http" 10 | "os" 11 | "path" 12 | "strings" 13 | "text/template" 14 | ) 15 | 16 | type Args struct { 17 | zversion string 18 | pages string 19 | comment_width uint 20 | templsource string 21 | headersource string 22 | } 23 | 24 | var args = Args{ 25 | zversion: "2.1,2.2,3.2,4.0", 26 | pages: "getsockopt,setsockopt", 27 | comment_width: 72, 28 | templsource: "./gozmqgen/template.txt", 29 | headersource: "./gozmqgen/header.txt", 30 | } 31 | 32 | func main() { 33 | flag.StringVar(&args.zversion, "zversion", args.zversion, "version of zmq") 34 | flag.StringVar(&args.pages, "pages", args.pages, "comma-delimited man page names") 35 | flag.UintVar(&args.comment_width, "comment-width", args.comment_width, "maximum width of comment text") 36 | flag.StringVar(&args.templsource, "template", args.templsource, "Name of template file or - to read STDIN.") 37 | flag.StringVar(&args.headersource, "header", args.headersource, "Name of header file.") 38 | flag.Parse() 39 | 40 | if len(args.templsource) == 0 { 41 | panic("'template' is required.") 42 | } 43 | 44 | data := map[string]interface{}{ 45 | "copyright": string(mustRead(args.headersource)), 46 | } 47 | for _, version := range strings.Split(args.zversion, ",") { 48 | data["build"] = buildtags[version] 49 | data["version"] = version 50 | for _, page := range strings.Split(args.pages, ",") { 51 | manual, err := LoadManual(version, "zmq_"+page) 52 | if err != nil { 53 | panic(err.Error()) 54 | } 55 | defer manual.Close() 56 | cite := "http://api.zeromq.org/" + version + ":zmq-" + page 57 | var options []map[string]interface{} 58 | optlist, err := ParseOptions(version, manual) 59 | if err != nil { 60 | panic(err.Error()) 61 | } 62 | for _, o := range optlist { 63 | o.SetCitation(cite + "#" + o.anchor) 64 | if !ignore[""][o.shortname] && !ignore[version][o.shortname] { 65 | options = append(options, o.Pod()) 66 | } 67 | } 68 | data[page] = map[string]interface{}{ 69 | "cite": cite, 70 | "options": options, 71 | } 72 | } 73 | raw_template := mustRead(args.templsource) 74 | t, err := template.New("main").Parse(string(raw_template)) 75 | if err != nil { 76 | panic(err.Error()) 77 | } 78 | out, err := os.Create("zmqgen_" + strings.Replace(version, ".", "_", -1) + ".go") 79 | if err != nil { 80 | panic(err.Error()) 81 | } else if err = t.Execute(out, data); err != nil { 82 | panic(err.Error()) 83 | } 84 | } 85 | } 86 | 87 | var ( 88 | gotypes = map[string]map[string]string{ 89 | "binary data": map[string]string{ 90 | "": "string", 91 | }, 92 | "binary data or Z85 text string": map[string]string{ 93 | "": "string", 94 | }, 95 | "character string": map[string]string{ 96 | "": "string", 97 | }, 98 | "int": map[string]string{ 99 | "": "int", 100 | "boolean": "bool", 101 | "milliseconds": "time.Duration", 102 | }, 103 | "int on POSIX systems, SOCKET on Windows": map[string]string{ 104 | "": "int", 105 | }, 106 | "int64_t": map[string]string{ 107 | "": "int64", 108 | "boolean": "bool", 109 | "milliseconds": "time.Duration", 110 | }, 111 | "NULL-terminated character string": map[string]string{ 112 | "": "string", 113 | }, 114 | "uint32_t": map[string]string{ 115 | "": "uint32", 116 | }, 117 | "uint64_t": map[string]string{ 118 | "": "uint64", 119 | "boolean": "bool", 120 | }, 121 | } 122 | 123 | ztypes = map[string]map[string]string{ 124 | "binary data": map[string]string{"": "String"}, 125 | "binary data or Z85 text string": map[string]string{"": "String"}, 126 | "character string": map[string]string{"": "String"}, 127 | "int": map[string]string{"": "Int"}, 128 | "int on POSIX systems, SOCKET on Windows": map[string]string{"": "Int"}, 129 | "int64_t": map[string]string{"": "Int64"}, 130 | "NULL-terminated character string": map[string]string{"": "String"}, 131 | "uint32_t": map[string]string{"": "UInt32"}, 132 | "uint64_t": map[string]string{"": "UInt64"}, 133 | } 134 | 135 | lowtypes = map[string]string{ 136 | "int32_t": "int32", 137 | "int64_t": "int64", 138 | "uint32_t": "uint32", 139 | "uint64_t": "uint64", 140 | } 141 | 142 | replacements = map[string]string{ 143 | "buf": "Buf", 144 | "Hwm": "HWM", 145 | "hwm": "HWM", 146 | "Ipv4only": "IPv4Only", 147 | "more": "More", 148 | "msg": "Msg", 149 | "pub": "PUB", 150 | "Router": "ROUTER", 151 | "size": "Size", 152 | "Tcp": "TCP", 153 | "timeo": "Timeout", 154 | } 155 | 156 | cachedir = path.Join(".cache", "codegen") 157 | 158 | // version : shortname : C type 159 | fixedtypes = map[string]map[string]string{ 160 | "": map[string]string{ 161 | "EVENTS": "uint64_t", 162 | "FD": "int", 163 | "RATE": "int64_t", 164 | "RCVBUF": "uint64_t", 165 | "RECOVERY_IVL": "int64_t", 166 | "SNDBUF": "uint64_t", 167 | "TYPE": "uint64_t", 168 | }, 169 | "2.1": map[string]string{ 170 | "RCVMORE": "uint64_t", 171 | }, 172 | "2.2": map[string]string{ 173 | "RCVMORE": "uint64_t", 174 | }, 175 | } 176 | 177 | fixedgotypes = map[string]string{ 178 | "TYPE": "SocketType", 179 | } 180 | 181 | // shortname : unit 182 | fixedunits = map[string]string{ 183 | "DELAY_ATTACH_ON_CONNECT": "boolean", 184 | "ROUTER_MANDATORY": "boolean", 185 | "XPUB_VERBOSE": "boolean", 186 | } 187 | 188 | // version : shortname 189 | ignore = map[string]map[string]bool{ 190 | "": map[string]bool{ 191 | "FD": true, 192 | "LAST_ENDPOINT": true, 193 | "MULTICAST_HOPS": true, 194 | }, 195 | "2.1": map[string]bool{ 196 | "RECOVERY_IVL": true, 197 | }, 198 | "2.2": map[string]bool{ 199 | "RECOVERY_IVL": true, 200 | }, 201 | "3.2": map[string]bool{}, 202 | } 203 | 204 | // shortname : shortname 205 | rename = map[string]string{ 206 | "RECOVERY_IVL_MSEC": "RECOVERY_IVL", 207 | } 208 | 209 | buildtags = map[string]string{ 210 | "2.1": "zmq_2_1", 211 | "2.2": "!zmq_2_1,!zmq_3_x,!zmq_4_x", 212 | "3.2": "zmq_3_x", 213 | "4.0": "zmq_4_x", 214 | } 215 | ) 216 | 217 | func fix(s string) string { 218 | for key, value := range replacements { 219 | s = strings.Replace(s, key, value, -1) 220 | } 221 | return s 222 | } 223 | 224 | func LoadManual(version string, funcname string) (io.ReadCloser, error) { 225 | pagename := version + ":" + funcname 226 | pagename = strings.Replace(pagename, ".", "-", -1) 227 | pagename = strings.Replace(pagename, "_", "-", -1) 228 | cachepath := path.Join(cachedir, pagename) 229 | cachefile, err := os.Open(cachepath) 230 | if err == nil { 231 | return cachefile, nil 232 | } 233 | os.MkdirAll(cachedir, 0755) 234 | url := "http://api.zeromq.org/" + pagename 235 | resp, err := http.Get(url) 236 | if err != nil { 237 | return nil, err 238 | } 239 | defer resp.Body.Close() 240 | if resp.StatusCode != 200 { 241 | return nil, fmt.Errorf("%s -> %s", url, resp.Status) 242 | } 243 | if cachefile, err = os.Create(cachepath); err != nil { 244 | return nil, err 245 | } 246 | if _, err := io.Copy(cachefile, resp.Body); err != nil { 247 | return nil, err 248 | } 249 | return os.Open(cachepath) 250 | } 251 | 252 | type Option struct { 253 | typ string // type as listed in source documentation 254 | unit string // unit as listed source documentation 255 | fullname string // e.g. "ZMQ_RCVMORE" 256 | shortname string // e.g. "RCVMORE" 257 | desc []string // one or more paragraphs 258 | cite string // URL to source documentation 259 | ctype string // C type e.g. "uint64_t" 260 | gotype string // Go type e.g. "SocketType" 261 | ztype string // option method suffix e.g. "Int64" 262 | lowtype string // go equivalent of C type e.g. "uint64" 263 | anchor string // id in source documentation 264 | duration bool // true if gotype=="time.Duration" 265 | gounit string // e.g. "time.Millisecond" 266 | cast bool // true if gotype needs casting 267 | } 268 | 269 | func NewOption(fullname string) *Option { 270 | return &Option{ 271 | fullname: fullname, 272 | shortname: fullname[4:], 273 | } 274 | } 275 | 276 | func (o *Option) Name() (name string) { 277 | shortname, ok := rename[o.shortname] 278 | if !ok { 279 | shortname = o.shortname 280 | } 281 | for _, part := range strings.Split(shortname, "_") { 282 | name = name + string(part[0]) + strings.ToLower(part[1:]) 283 | } 284 | return fix(name) 285 | } 286 | 287 | func (o *Option) AppendDescription(line string) { 288 | line = strings.TrimSpace(line) 289 | if len(line) > 0 { 290 | o.desc = append(o.desc, line) 291 | } 292 | } 293 | 294 | func (o *Option) SetCitation(cite string) { 295 | o.cite = cite 296 | } 297 | 298 | func (o *Option) Comment() (comment string) { 299 | desc := o.desc[1:] 300 | if len(o.cite) > 0 { 301 | desc = append([]string{o.cite, ""}, desc...) 302 | } 303 | for _, line := range desc { 304 | if len(line) > 0 && line[0] == ' ' { 305 | comment = comment + strings.TrimRight(line, "\n") + "\n" 306 | } else { 307 | // TODO: wrap line to width chars 308 | //wrapped = textwrap.wrap(line, width) 309 | //"\n".join(wrapped) + "\n%s\n" % wrapped 310 | comment = comment + line 311 | } 312 | } 313 | return 314 | } 315 | 316 | func (o *Option) Summary() string { 317 | return o.fullname + ": " + o.desc[0] + "." 318 | } 319 | 320 | func (o *Option) Pod() map[string]interface{} { 321 | return map[string]interface{}{ 322 | "fullname": o.fullname, 323 | "shortname": o.shortname, 324 | "nicename": o.Name(), 325 | "summary": o.Summary(), 326 | "description": strings.Split(o.Comment(), "\n"), 327 | "ctype": o.typ, 328 | "gotype": o.gotype, 329 | "ztype": o.ztype, 330 | "lowtype": o.lowtype, 331 | "anchor": o.anchor, 332 | "duration": o.duration, 333 | "citation": o.cite, 334 | "boolean": o.gotype == "bool", 335 | "gounit": o.gounit, 336 | "cast": o.cast, 337 | } 338 | } 339 | 340 | func (o *Option) String() string { return o.Name() } 341 | 342 | type OptionsBuilder struct { 343 | options []*Option 344 | version string 345 | } 346 | 347 | func (b *OptionsBuilder) Add(name string, info string) bool { 348 | if !strings.HasPrefix(name, "ZMQ_") { 349 | return false 350 | } 351 | option := NewOption(name) 352 | b.options = append(b.options, option) 353 | option.AppendDescription(info) 354 | return true 355 | } 356 | 357 | func (b *OptionsBuilder) Describe(info string) { 358 | if len(b.options) > 0 { 359 | b.options[len(b.options)-1].AppendDescription(info) 360 | } 361 | } 362 | 363 | func (b *OptionsBuilder) SetAnchor(anchor string) { 364 | if len(b.options) > 0 { 365 | b.options[len(b.options)-1].anchor = anchor 366 | } 367 | } 368 | 369 | func (b *OptionsBuilder) SetProperty(name string, value string) { 370 | if len(b.options) > 0 { 371 | option := b.options[len(b.options)-1] 372 | name = strings.TrimSpace(name) 373 | switch name { 374 | case "Option value type": 375 | option.typ = value 376 | break 377 | case "Option value unit": 378 | option.unit = value 379 | break 380 | case "Option value size": 381 | option.unit = "Z85" 382 | break 383 | } 384 | if len(option.typ) > 0 && len(option.unit) > 0 { 385 | if val, ok := fixedtypes[""][option.shortname]; ok { 386 | option.typ = val 387 | } else if val, ok := fixedtypes[b.version][option.shortname]; ok { 388 | option.typ = val 389 | } 390 | if val, ok := lowtypes[option.typ]; ok { 391 | option.lowtype = val 392 | } else { 393 | option.lowtype = option.typ 394 | } 395 | if val, ok := fixedunits[option.shortname]; ok { 396 | option.unit = val 397 | } 398 | gomap := gotypes[option.typ] 399 | if val, ok := gomap[option.unit]; ok { 400 | option.gotype = val 401 | } else { 402 | option.gotype = gomap[""] 403 | } 404 | if val, ok := fixedgotypes[option.shortname]; ok { 405 | option.gotype = val 406 | option.cast = true 407 | } 408 | zmap := ztypes[option.typ] 409 | if val, ok := zmap[option.unit]; ok { 410 | option.ztype = val 411 | } else { 412 | option.ztype = zmap[""] 413 | } 414 | if option.gotype == "time.Duration" { 415 | option.duration = true 416 | switch option.unit { 417 | case "milliseconds": 418 | option.gounit = "time.Millisecond" 419 | case "seconds": 420 | option.gounit = "time.Second" 421 | } 422 | } 423 | } 424 | option.AppendDescription(fmt.Sprintf(" %-25s %s\n", name, value)) 425 | } 426 | } 427 | 428 | func ParseOptions(version string, r io.Reader) ([]*Option, error) { 429 | d := xml.NewDecoder(r) 430 | d.Strict = false 431 | d.AutoClose = xml.HTMLAutoClose 432 | d.Entity = xml.HTMLEntity 433 | b := &OptionsBuilder{version: version} 434 | var state, text, text2 string 435 | for { 436 | t, err := d.Token() 437 | if err == io.EOF { 438 | break 439 | } else if err != nil { 440 | return nil, err 441 | } else { 442 | switch token := t.(type) { 443 | case xml.StartElement: 444 | switch token.Name.Local { 445 | case "h3": 446 | state = "title" 447 | text = "" 448 | text2 = "unknown" 449 | for _, attr := range token.Attr { 450 | switch attr.Name.Local { 451 | case "id": 452 | text2 = attr.Value 453 | } 454 | } 455 | case "table": 456 | switch state { 457 | case "describing": 458 | for _, attr := range token.Attr { 459 | switch attr.Name.Local { 460 | case "class": 461 | if attr.Value == "wiki-content-table" { 462 | b.Describe(text) 463 | text = "" 464 | state = "properties" 465 | } 466 | } 467 | } 468 | } 469 | case "td": 470 | switch state { 471 | case "properties": 472 | state = "property-name" 473 | case "property-name": 474 | state = "property-value" 475 | } 476 | } 477 | case xml.EndElement: 478 | switch state { 479 | case "title": 480 | switch token.Name.Local { 481 | case "h3": 482 | parts := strings.SplitN(text, ": ", 2) 483 | if b.Add(parts[0], parts[1]) { 484 | state = "describing" 485 | b.SetAnchor(text2) 486 | } else { 487 | state = "" 488 | } 489 | text = "" 490 | text2 = "" 491 | } 492 | case "describing": 493 | switch token.Name.Local { 494 | case "p", "li": 495 | b.Describe(text) 496 | text = "" 497 | } 498 | case "properties": 499 | switch token.Name.Local { 500 | case "table": 501 | state = "" 502 | } 503 | case "property-value": 504 | switch token.Name.Local { 505 | case "td": 506 | b.SetProperty(text, text2) 507 | state = "properties" 508 | text = "" 509 | text2 = "" 510 | } 511 | } 512 | case xml.CharData: 513 | switch state { 514 | case "title": 515 | text += string(token) 516 | case "describing": 517 | text += string(token) 518 | case "property-name": 519 | text += string(token) 520 | case "property-value": 521 | text2 += string(token) 522 | } 523 | } 524 | } 525 | } 526 | return b.options, nil 527 | } 528 | 529 | func mustRead(name string) []byte { 530 | var raw []byte 531 | var err error 532 | if name == "-" { 533 | raw, err = ioutil.ReadAll(os.Stdin) 534 | } else { 535 | raw, err = ioutil.ReadFile(name) 536 | } 537 | if err != nil { 538 | panic(err.Error()) 539 | } 540 | return raw 541 | } 542 | -------------------------------------------------------------------------------- /gozmqgen/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // This test depends on a remote HTTP service that may not even be available. 8 | func TestLoadManual(t *testing.T) { 9 | if m, err := LoadManual("3.2", "zmq-setsockopt"); err != nil { 10 | t.Errorf(err.Error()) 11 | } else if m == nil { 12 | t.Errorf("no error yet nil reader.") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gozmqgen/template.txt: -------------------------------------------------------------------------------- 1 | // +build {{.build}} 2 | // 3 | {{if .copyright}}{{.copyright}} 4 | {{end}} 5 | package gozmq 6 | 7 | import ( 8 | "time" 9 | ) 10 | 11 | // This file was {{/*NOT */}}generated automatically. Changes made here will {{/*NOT */}}be lost. 12 | 13 | // Socket Option Getters{{with .getsockopt}}{{range .options}} 14 | 15 | // {{.summary}} 16 | // 17 | // See: {{.citation}} 18 | // 19 | func (s *Socket) {{.nicename}}() ({{.gotype}}, error) { 20 | {{if .duration}}ms, err := s.GetSockOpt{{.ztype}}({{.shortname}}) 21 | return time.Duration(ms) * {{.gounit}}, err{{else}}{{if .boolean}}value, err := s.GetSockOpt{{.ztype}}({{.shortname}}) 22 | return value != 0, err{{else}}{{if .cast}}value, err := s.GetSockOpt{{.ztype}}({{.shortname}}) 23 | return {{.gotype}}(value), err{{else}}return s.GetSockOpt{{.ztype}}({{.shortname}}){{end}}{{end}}{{end}} 24 | }{{end}}{{end}} 25 | 26 | // Socket Option Setters{{with .setsockopt}}{{range .options}} 27 | 28 | // {{.summary}} 29 | // 30 | // See: {{.citation}} 31 | // 32 | func (s *Socket) Set{{.nicename}}(value {{.gotype}}) error { 33 | {{if .duration}}return s.SetSockOpt{{.ztype}}({{.shortname}}, {{.lowtype}}(value/{{.gounit}})){{else}}{{if .boolean}}if value { 34 | return s.SetSockOpt{{.ztype}}({{.shortname}}, 1) 35 | } 36 | return s.SetSockOpt{{.ztype}}({{.shortname}}, 0){{else}}return s.SetSockOpt{{.ztype}}({{.shortname}}, {{if .cast}}{{.lowtype}}({{end}}value{{if .cast}}){{end}}){{end}}{{end}} 37 | }{{end}}{{end}} 38 | -------------------------------------------------------------------------------- /zmq.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010-2012 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Go (golang) Bindings for 0mq (zmq, zeromq) 18 | package gozmq 19 | 20 | /* 21 | #cgo pkg-config: libzmq 22 | #include 23 | #include 24 | #include 25 | */ 26 | import "C" 27 | 28 | import ( 29 | "errors" 30 | "sync" 31 | "syscall" 32 | "time" 33 | "unsafe" 34 | ) 35 | 36 | type SocketType int 37 | 38 | type IntSocketOption int 39 | type Int64SocketOption int 40 | type UInt64SocketOption int 41 | type StringSocketOption int 42 | type BoolSocketOption int 43 | 44 | type MessageOption int 45 | type SendRecvOption int 46 | 47 | const ( 48 | // NewSocket types 49 | PAIR = SocketType(C.ZMQ_PAIR) 50 | PUB = SocketType(C.ZMQ_PUB) 51 | SUB = SocketType(C.ZMQ_SUB) 52 | REQ = SocketType(C.ZMQ_REQ) 53 | REP = SocketType(C.ZMQ_REP) 54 | DEALER = SocketType(C.ZMQ_DEALER) 55 | ROUTER = SocketType(C.ZMQ_ROUTER) 56 | PULL = SocketType(C.ZMQ_PULL) 57 | PUSH = SocketType(C.ZMQ_PUSH) 58 | XPUB = SocketType(C.ZMQ_XPUB) 59 | XSUB = SocketType(C.ZMQ_XSUB) 60 | 61 | // Deprecated aliases 62 | XREQ = DEALER 63 | XREP = ROUTER 64 | UPSTREAM = PULL 65 | DOWNSTREAM = PUSH 66 | 67 | // NewSocket options 68 | AFFINITY = UInt64SocketOption(C.ZMQ_AFFINITY) 69 | IDENTITY = StringSocketOption(C.ZMQ_IDENTITY) 70 | SUBSCRIBE = StringSocketOption(C.ZMQ_SUBSCRIBE) 71 | UNSUBSCRIBE = StringSocketOption(C.ZMQ_UNSUBSCRIBE) 72 | RATE = Int64SocketOption(C.ZMQ_RATE) 73 | RECOVERY_IVL = Int64SocketOption(C.ZMQ_RECOVERY_IVL) 74 | SNDBUF = UInt64SocketOption(C.ZMQ_SNDBUF) 75 | RCVBUF = UInt64SocketOption(C.ZMQ_RCVBUF) 76 | FD = Int64SocketOption(C.ZMQ_FD) 77 | EVENTS = UInt64SocketOption(C.ZMQ_EVENTS) 78 | TYPE = UInt64SocketOption(C.ZMQ_TYPE) 79 | LINGER = IntSocketOption(C.ZMQ_LINGER) 80 | RECONNECT_IVL = IntSocketOption(C.ZMQ_RECONNECT_IVL) 81 | RECONNECT_IVL_MAX = IntSocketOption(C.ZMQ_RECONNECT_IVL_MAX) 82 | BACKLOG = IntSocketOption(C.ZMQ_BACKLOG) 83 | 84 | // Send/recv options 85 | SNDMORE = SendRecvOption(C.ZMQ_SNDMORE) 86 | ) 87 | 88 | type zmqErrno syscall.Errno 89 | 90 | var ( 91 | // Additional ZMQ errors 92 | ENOTSOCK error = zmqErrno(C.ENOTSOCK) 93 | EFSM error = zmqErrno(C.EFSM) 94 | EINVAL error = syscall.EINVAL 95 | ENOCOMPATPROTO error = zmqErrno(C.ENOCOMPATPROTO) 96 | ETERM error = zmqErrno(C.ETERM) 97 | EMTHREAD error = zmqErrno(C.EMTHREAD) 98 | ) 99 | 100 | type PollEvents C.short 101 | 102 | const ( 103 | POLLIN = PollEvents(C.ZMQ_POLLIN) 104 | POLLOUT = PollEvents(C.ZMQ_POLLOUT) 105 | POLLERR = PollEvents(C.ZMQ_POLLERR) 106 | ) 107 | 108 | type DeviceType int 109 | 110 | const ( 111 | STREAMER = DeviceType(C.ZMQ_STREAMER) 112 | FORWARDER = DeviceType(C.ZMQ_FORWARDER) 113 | QUEUE = DeviceType(C.ZMQ_QUEUE) 114 | ) 115 | 116 | var ( 117 | pollunit time.Duration 118 | ) 119 | 120 | func init() { 121 | if v, _, _ := Version(); v < 3 { 122 | pollunit = time.Microsecond 123 | } else { 124 | pollunit = time.Millisecond 125 | } 126 | } 127 | 128 | // void zmq_version (int *major, int *minor, int *patch); 129 | func Version() (int, int, int) { 130 | var major, minor, patch C.int 131 | C.zmq_version(&major, &minor, &patch) 132 | return int(major), int(minor), int(patch) 133 | } 134 | 135 | func (e zmqErrno) Error() string { 136 | return C.GoString(C.zmq_strerror(C.int(e))) 137 | } 138 | 139 | // If possible, convert a syscall.Errno to a zmqErrno. 140 | func casterr(fromcgo error) error { 141 | errno, ok := fromcgo.(syscall.Errno) 142 | if !ok { 143 | return fromcgo 144 | } 145 | zmqerrno := zmqErrno(errno) 146 | switch zmqerrno { 147 | case ENOTSOCK: 148 | return zmqerrno 149 | } 150 | if zmqerrno >= C.ZMQ_HAUSNUMERO { 151 | return zmqerrno 152 | } 153 | return errno 154 | } 155 | 156 | func getErrorForTesting() error { 157 | return zmqErrno(C.EFSM) 158 | } 159 | 160 | /* 161 | * A context handles socket creation and asynchronous message delivery. 162 | * There should generally be one context per application. 163 | */ 164 | type Context struct { 165 | c unsafe.Pointer 166 | mutex sync.Mutex // ensure init is only called once 167 | init func() // func that calls zmq_init 168 | err error // error returned from zmq_init 169 | iothreads int // hold the iothreads option until zmq_init time 170 | } 171 | 172 | // Create a new context. 173 | func NewContext() (*Context, error) { 174 | c := &Context{iothreads: 1} 175 | c.init = func() { 176 | c.mutex.Lock() 177 | defer c.mutex.Unlock() 178 | if c.c == nil && c.err == nil { 179 | // C.NULL is correct but causes a runtime failure on darwin at present 180 | if ptr, err := C.zmq_init(C.int(c.iothreads)); ptr != nil /*C.NULL*/ { 181 | c.c = ptr 182 | } else { 183 | c.err = casterr(err) 184 | } 185 | } 186 | } 187 | return c, nil 188 | } 189 | 190 | func (c *Context) Close() { 191 | // C.NULL is correct but causes a runtime failure on darwin at present 192 | if c.c != nil /*C.NULL*/ { 193 | C.zmq_term(c.c) 194 | } 195 | } 196 | 197 | // Create a new socket. 198 | // void *zmq_socket (void *context, int type); 199 | func (c *Context) NewSocket(t SocketType) (*Socket, error) { 200 | if c.init(); c.err != nil { 201 | return nil, c.err 202 | } 203 | s, err := C.zmq_socket(c.c, C.int(t)) 204 | // C.NULL is correct but causes a runtime failure on darwin at present 205 | if s != nil /*C.NULL*/ { 206 | return &Socket{c: c, s: s}, nil 207 | } 208 | return nil, casterr(err) 209 | } 210 | 211 | type Socket struct { 212 | // XXX Ensure the zmq context doesn't get destroyed underneath us. 213 | c *Context 214 | s unsafe.Pointer 215 | } 216 | 217 | // Shutdown the socket. 218 | // int zmq_close (void *s); 219 | func (s *Socket) Close() error { 220 | if s.c == nil { 221 | return ENOTSOCK 222 | } 223 | if rc, err := C.zmq_close(s.s); rc != 0 { 224 | return casterr(err) 225 | } 226 | s.c = nil 227 | return nil 228 | } 229 | 230 | // Set an int option on the socket. 231 | // int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); 232 | func (s *Socket) SetSockOptInt(option IntSocketOption, value int) error { 233 | val := C.int(value) 234 | if rc, err := C.zmq_setsockopt(s.s, C.int(option), unsafe.Pointer(&val), C.size_t(unsafe.Sizeof(val))); rc != 0 { 235 | return casterr(err) 236 | } 237 | return nil 238 | } 239 | 240 | // Set an int64 option on the socket. 241 | // int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); 242 | func (s *Socket) SetSockOptInt64(option Int64SocketOption, value int64) error { 243 | if rc, err := C.zmq_setsockopt(s.s, C.int(option), unsafe.Pointer(&value), C.size_t(unsafe.Sizeof(value))); rc != 0 { 244 | return casterr(err) 245 | } 246 | return nil 247 | } 248 | 249 | // Set a uint64 option on the socket. 250 | // int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); 251 | func (s *Socket) SetSockOptUInt64(option UInt64SocketOption, value uint64) error { 252 | if rc, err := C.zmq_setsockopt(s.s, C.int(option), unsafe.Pointer(&value), C.size_t(unsafe.Sizeof(value))); rc != 0 { 253 | return casterr(err) 254 | } 255 | return nil 256 | } 257 | 258 | // Set a string option on the socket. 259 | // int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); 260 | func (s *Socket) SetSockOptString(option StringSocketOption, value string) error { 261 | v := C.CString(value) 262 | defer C.free(unsafe.Pointer(v)) 263 | if rc, err := C.zmq_setsockopt(s.s, C.int(option), unsafe.Pointer(v), C.size_t(len(value))); rc != 0 { 264 | return casterr(err) 265 | } 266 | return nil 267 | } 268 | 269 | // Set a string option on the socket to nil. 270 | // int zmq_setsockopt (void *s, int option, const void *optval, size_t optvallen); 271 | func (s *Socket) SetSockOptStringNil(option StringSocketOption) error { 272 | if rc, err := C.zmq_setsockopt(s.s, C.int(option), nil, 0); rc != 0 { 273 | return casterr(err) 274 | } 275 | return nil 276 | } 277 | 278 | // Get an int option from the socket. 279 | // int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); 280 | func (s *Socket) GetSockOptInt(option IntSocketOption) (value int, err error) { 281 | size := C.size_t(unsafe.Sizeof(value)) 282 | var rc C.int 283 | if rc, err = C.zmq_getsockopt(s.s, C.int(option), unsafe.Pointer(&value), &size); rc != 0 { 284 | err = casterr(err) 285 | return 286 | } 287 | return 288 | } 289 | 290 | // Get an int64 option from the socket. 291 | // int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); 292 | func (s *Socket) GetSockOptInt64(option Int64SocketOption) (value int64, err error) { 293 | size := C.size_t(unsafe.Sizeof(value)) 294 | var rc C.int 295 | if rc, err = C.zmq_getsockopt(s.s, C.int(option), unsafe.Pointer(&value), &size); rc != 0 { 296 | err = casterr(err) 297 | return 298 | } 299 | return 300 | } 301 | 302 | // Get a uint64 option from the socket. 303 | // int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); 304 | func (s *Socket) GetSockOptUInt64(option UInt64SocketOption) (value uint64, err error) { 305 | size := C.size_t(unsafe.Sizeof(value)) 306 | var rc C.int 307 | if rc, err = C.zmq_getsockopt(s.s, C.int(option), unsafe.Pointer(&value), &size); rc != 0 { 308 | println("GetSockOptUInt64:", err.Error()) 309 | err = casterr(err) 310 | return 311 | } 312 | return 313 | } 314 | 315 | // Get a string option from the socket. 316 | // int zmq_getsockopt (void *s, int option, void *optval, size_t *optvallen); 317 | func (s *Socket) GetSockOptString(option StringSocketOption) (value string, err error) { 318 | var buffer [1024]byte 319 | var size C.size_t = 1024 320 | var rc C.int 321 | if rc, err = C.zmq_getsockopt(s.s, C.int(option), unsafe.Pointer(&buffer), &size); rc != 0 { 322 | err = casterr(err) 323 | return 324 | } 325 | value = string(buffer[:size]) 326 | return 327 | } 328 | 329 | func (s *Socket) GetSockOptBool(option BoolSocketOption) (value bool, err error) { 330 | size := C.size_t(unsafe.Sizeof(value)) 331 | var rc C.int 332 | if rc, err = C.zmq_getsockopt(s.s, C.int(option), unsafe.Pointer(&value), &size); rc != 0 { 333 | err = casterr(err) 334 | return 335 | } 336 | return 337 | } 338 | 339 | // Bind the socket to a listening address. 340 | // int zmq_bind (void *s, const char *addr); 341 | func (s *Socket) Bind(address string) error { 342 | a := C.CString(address) 343 | defer C.free(unsafe.Pointer(a)) 344 | if rc, err := C.zmq_bind(s.s, a); rc != 0 { 345 | return casterr(err) 346 | } 347 | return nil 348 | } 349 | 350 | // Connect the socket to an address. 351 | // int zmq_connect (void *s, const char *addr); 352 | func (s *Socket) Connect(address string) error { 353 | if s.c == nil { 354 | return ENOTSOCK 355 | } 356 | a := C.CString(address) 357 | defer C.free(unsafe.Pointer(a)) 358 | if rc, err := C.zmq_connect(s.s, a); rc != 0 { 359 | return casterr(err) 360 | } 361 | return nil 362 | } 363 | 364 | // Send a multipart message. 365 | func (s *Socket) SendMultipart(parts [][]byte, flags SendRecvOption) (err error) { 366 | for i := 0; i < len(parts)-1; i++ { 367 | if err = s.Send(parts[i], SNDMORE|flags); err != nil { 368 | return 369 | } 370 | } 371 | err = s.Send(parts[(len(parts)-1)], flags) 372 | return 373 | } 374 | 375 | // Receive a multipart message. 376 | func (s *Socket) RecvMultipart(flags SendRecvOption) (parts [][]byte, err error) { 377 | parts = make([][]byte, 0) 378 | for { 379 | var data []byte 380 | var more bool 381 | 382 | data, err = s.Recv(flags) 383 | if err != nil { 384 | return 385 | } 386 | parts = append(parts, data) 387 | more, err = s.getRcvmore() 388 | if err != nil { 389 | return 390 | } 391 | if !more { 392 | break 393 | } 394 | } 395 | return 396 | } 397 | 398 | // return the 399 | func (s *Socket) apiSocket() unsafe.Pointer { 400 | return s.s 401 | } 402 | 403 | // Item to poll for read/write events on, either a *Socket or a file descriptor 404 | type PollItem struct { 405 | Socket *Socket // socket to poll for events on 406 | Fd ZmqOsSocketType // fd to poll for events on as returned from os.File.Fd() 407 | Events PollEvents // event set to poll for 408 | REvents PollEvents // events that were present 409 | } 410 | 411 | // a set of items to poll for events on 412 | type PollItems []PollItem 413 | 414 | // Poll ZmqSockets and file descriptors for I/O readiness. Timeout is in 415 | // time.Duration. The smallest possible timeout is time.Millisecond for 416 | // ZeroMQ version 3 and above, and time.Microsecond for earlier versions. 417 | func Poll(items []PollItem, timeout time.Duration) (count int, err error) { 418 | zitems := make([]C.zmq_pollitem_t, len(items)) 419 | for i, pi := range items { 420 | zitems[i].socket = pi.Socket.apiSocket() 421 | zitems[i].fd = pi.Fd.ToRaw() 422 | zitems[i].events = C.short(pi.Events) 423 | } 424 | ztimeout := C.long(-1) 425 | if timeout >= 0 { 426 | ztimeout = C.long(uint64(timeout / pollunit)) 427 | } 428 | rc, err := C.zmq_poll(&zitems[0], C.int(len(zitems)), ztimeout) 429 | if rc == -1 { 430 | return 0, casterr(err) 431 | } 432 | 433 | for i, zi := range zitems { 434 | items[i].REvents = PollEvents(zi.revents) 435 | } 436 | 437 | return int(rc), nil 438 | } 439 | 440 | // run a zmq_device passing messages between in and out 441 | func Device(t DeviceType, in, out *Socket) error { 442 | if rc, err := C.zmq_device(C.int(t), in.apiSocket(), out.apiSocket()); rc != 0 { 443 | return casterr(err) 444 | } 445 | return errors.New("zmq_device() returned unexpectedly.") 446 | } 447 | 448 | // XXX For now, this library abstracts zmq_msg_t out of the API. 449 | // int zmq_msg_init (zmq_msg_t *msg); 450 | // int zmq_msg_init_size (zmq_msg_t *msg, size_t size); 451 | // int zmq_msg_close (zmq_msg_t *msg); 452 | // size_t zmq_msg_size (zmq_msg_t *msg); 453 | // void *zmq_msg_data (zmq_msg_t *msg); 454 | // int zmq_msg_copy (zmq_msg_t *dest, zmq_msg_t *src); 455 | // int zmq_msg_move (zmq_msg_t *dest, zmq_msg_t *src); 456 | -------------------------------------------------------------------------------- /zmq_2_2.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_2_1 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo pkg-config: libzmq 23 | #include 24 | */ 25 | import "C" 26 | 27 | const ( 28 | RCVTIMEO = IntSocketOption(C.ZMQ_RCVTIMEO) 29 | SNDTIMEO = IntSocketOption(C.ZMQ_SNDTIMEO) 30 | ) 31 | -------------------------------------------------------------------------------- /zmq_2_x.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_3_x,!zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | import "unsafe" 29 | 30 | const ( 31 | RCVMORE = UInt64SocketOption(C.ZMQ_RCVMORE) 32 | RECOVERY_IVL_MSEC = Int64SocketOption(C.ZMQ_RECOVERY_IVL_MSEC) 33 | SWAP = Int64SocketOption(C.ZMQ_SWAP) 34 | MCAST_LOOP = Int64SocketOption(C.ZMQ_MCAST_LOOP) 35 | HWM = UInt64SocketOption(C.ZMQ_HWM) 36 | NOBLOCK = SendRecvOption(C.ZMQ_NOBLOCK) 37 | 38 | // Forwards-compatible aliases: 39 | DONTWAIT = NOBLOCK 40 | ) 41 | 42 | // Get a context option. 43 | func (c *Context) IOThreads() (int, error) { 44 | return c.iothreads, nil 45 | } 46 | 47 | // Set a context option. 48 | func (c *Context) SetIOThreads(value int) error { 49 | c.iothreads = value 50 | return nil 51 | } 52 | 53 | // Send a message to the socket. 54 | // int zmq_send (void *s, zmq_msg_t *msg, int flags); 55 | func (s *Socket) Send(data []byte, flags SendRecvOption) error { 56 | var m C.zmq_msg_t 57 | // Copy data array into C-allocated buffer. 58 | size := C.size_t(len(data)) 59 | 60 | if rc, err := C.zmq_msg_init_size(&m, size); rc != 0 { 61 | return casterr(err) 62 | } 63 | 64 | if size > 0 { 65 | // FIXME Ideally this wouldn't require a copy. 66 | C.memcpy(C.zmq_msg_data(&m), unsafe.Pointer(&data[0]), size) // XXX I hope this works...(seems to) 67 | } 68 | 69 | if rc, err := C.zmq_send(s.s, &m, C.int(flags)); rc != 0 { 70 | // zmq_send did not take ownership, free message 71 | C.zmq_msg_close(&m) 72 | return casterr(err) 73 | } 74 | return nil 75 | } 76 | 77 | // Receive a message from the socket. 78 | // int zmq_recv (void *s, zmq_msg_t *msg, int flags); 79 | func (s *Socket) Recv(flags SendRecvOption) (data []byte, err error) { 80 | // Allocate and initialise a new zmq_msg_t 81 | var m C.zmq_msg_t 82 | var rc C.int 83 | if rc, err = C.zmq_msg_init(&m); rc != 0 { 84 | err = casterr(err) 85 | return 86 | } 87 | defer C.zmq_msg_close(&m) 88 | // Receive into message 89 | if rc, err = C.zmq_recv(s.s, &m, C.int(flags)); rc != 0 { 90 | err = casterr(err) 91 | return 92 | } 93 | err = nil 94 | // Copy message data into a byte array 95 | // FIXME Ideally this wouldn't require a copy. 96 | size := C.zmq_msg_size(&m) 97 | if size > 0 { 98 | data = C.GoBytes(C.zmq_msg_data(&m), C.int(size)) 99 | } else { 100 | data = nil 101 | } 102 | return 103 | } 104 | 105 | // Portability helper 106 | func (s *Socket) getRcvmore() (more bool, err error) { 107 | value, err := s.GetSockOptUInt64(RCVMORE) 108 | more = value != 0 109 | return 110 | } 111 | -------------------------------------------------------------------------------- /zmq_3_x.go: -------------------------------------------------------------------------------- 1 | // +build zmq_3_x zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | import ( 29 | "errors" 30 | "unsafe" 31 | ) 32 | 33 | const ( 34 | RCVMORE = IntSocketOption(C.ZMQ_RCVMORE) 35 | SNDHWM = IntSocketOption(C.ZMQ_SNDHWM) 36 | RCVHWM = IntSocketOption(C.ZMQ_RCVHWM) 37 | 38 | // TODO Not documented in the man page... 39 | //LAST_ENDPOINT = UInt64SocketOption(C.ZMQ_LAST_ENDPOINT) 40 | DELAY_ATTACH_ON_CONNECT = IntSocketOption(C.ZMQ_DELAY_ATTACH_ON_CONNECT) 41 | FAIL_UNROUTABLE = BoolSocketOption(C.ZMQ_FAIL_UNROUTABLE) 42 | IPV4ONLY = IntSocketOption(C.ZMQ_IPV4ONLY) 43 | MAXMSGSIZE = Int64SocketOption(C.ZMQ_MAXMSGSIZE) 44 | ROUTER_MANDATORY = IntSocketOption(C.ZMQ_ROUTER_MANDATORY) 45 | TCP_KEEPALIVE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE) 46 | TCP_KEEPALIVE_CNT = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_CNT) 47 | TCP_KEEPALIVE_IDLE = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_IDLE) 48 | TCP_KEEPALIVE_INTVL = IntSocketOption(C.ZMQ_TCP_KEEPALIVE_INTVL) 49 | TCP_ACCEPT_FILTER = StringSocketOption(C.ZMQ_TCP_ACCEPT_FILTER) 50 | XPUB_VERBOSE = IntSocketOption(C.ZMQ_XPUB_VERBOSE) 51 | 52 | // Message options 53 | MORE = MessageOption(C.ZMQ_MORE) 54 | 55 | // Send/recv options 56 | DONTWAIT = SendRecvOption(C.ZMQ_DONTWAIT) 57 | 58 | // Deprecated aliases 59 | NOBLOCK = DONTWAIT 60 | ) 61 | 62 | // Socket transport events 63 | type Event int 64 | 65 | const ( 66 | EVENT_CONNECTED = Event(C.ZMQ_EVENT_CONNECTED) 67 | EVENT_CONNECT_DELAYED = Event(C.ZMQ_EVENT_CONNECT_DELAYED) 68 | EVENT_CONNECT_RETRIED = Event(C.ZMQ_EVENT_CONNECT_RETRIED) 69 | 70 | EVENT_LISTENING = Event(C.ZMQ_EVENT_LISTENING) 71 | EVENT_BIND_FAILED = Event(C.ZMQ_EVENT_BIND_FAILED) 72 | 73 | EVENT_ACCEPTED = Event(C.ZMQ_EVENT_ACCEPTED) 74 | EVENT_ACCEPT_FAILED = Event(C.ZMQ_EVENT_ACCEPT_FAILED) 75 | 76 | EVENT_CLOSED = Event(C.ZMQ_EVENT_CLOSED) 77 | EVENT_CLOSE_FAILED = Event(C.ZMQ_EVENT_CLOSE_FAILED) 78 | EVENT_DISCONNECTED = Event(C.ZMQ_EVENT_DISCONNECTED) 79 | 80 | EVENT_ALL = EVENT_CONNECTED | EVENT_CONNECT_DELAYED | 81 | EVENT_CONNECT_RETRIED | EVENT_LISTENING | EVENT_BIND_FAILED | 82 | EVENT_ACCEPTED | EVENT_ACCEPT_FAILED | EVENT_CLOSED | 83 | EVENT_CLOSE_FAILED | EVENT_DISCONNECTED 84 | ) 85 | 86 | // Get a context option. 87 | // int zmq_ctx_get (void *c, int); 88 | func (c *Context) get(option C.int) (int, error) { 89 | if c.init(); c.err != nil { 90 | return -1, c.err 91 | } 92 | var value C.int 93 | var err error 94 | if value, err = C.zmq_ctx_get(c.c, option); err != nil { 95 | return -1, casterr(err) 96 | } 97 | return int(value), nil 98 | } 99 | 100 | // Set a context option. 101 | // int zmq_ctx_set (void *c, int, int); 102 | func (c *Context) set(option C.int, value int) error { 103 | if c.init(); c.err != nil { 104 | return c.err 105 | } 106 | if rc, err := C.zmq_ctx_set(c.c, option, C.int(value)); rc == -1 { 107 | return casterr(err) 108 | } 109 | return nil 110 | } 111 | 112 | func (c *Context) IOThreads() (int, error) { 113 | return c.get(C.ZMQ_IO_THREADS) 114 | } 115 | 116 | func (c *Context) MaxSockets() (int, error) { 117 | return c.get(C.ZMQ_MAX_SOCKETS) 118 | } 119 | 120 | func (c *Context) SetIOThreads(value int) error { 121 | return c.set(C.ZMQ_IO_THREADS, value) 122 | } 123 | 124 | func (c *Context) SetMaxSockets(value int) error { 125 | return c.set(C.ZMQ_MAX_SOCKETS, value) 126 | } 127 | 128 | func (s *Socket) SetHWM(value int) error { 129 | snd := s.SetSndHWM(value) 130 | rcv := s.SetRcvHWM(value) 131 | if snd != nil { 132 | return snd 133 | } 134 | return rcv 135 | } 136 | 137 | func (s *Socket) SetTCPAcceptFilterNil() error { 138 | return s.SetSockOptStringNil(TCP_ACCEPT_FILTER) 139 | } 140 | 141 | // Disconnect the socket from the address. 142 | // int zmq_disconnect (void *s, const char *addr); 143 | func (s *Socket) Disconnect(address string) error { 144 | if s.c == nil { 145 | return ENOTSOCK 146 | } 147 | a := C.CString(address) 148 | defer C.free(unsafe.Pointer(a)) 149 | if rc, err := C.zmq_disconnect(s.s, a); rc != 0 { 150 | return casterr(err) 151 | } 152 | return nil 153 | } 154 | 155 | // Send a message to the socket. 156 | // int zmq_send (void *s, zmq_msg_t *msg, int flags); 157 | func (s *Socket) Send(data []byte, flags SendRecvOption) error { 158 | var m C.zmq_msg_t 159 | // Copy data array into C-allocated buffer. 160 | size := C.size_t(len(data)) 161 | 162 | if rc, err := C.zmq_msg_init_size(&m, size); rc != 0 { 163 | return casterr(err) 164 | } 165 | 166 | if size > 0 { 167 | // FIXME Ideally this wouldn't require a copy. 168 | C.memcpy(C.zmq_msg_data(&m), unsafe.Pointer(&data[0]), size) // XXX I hope this works...(seems to) 169 | } 170 | 171 | if rc, err := C.zmq_sendmsg(s.s, &m, C.int(flags)); rc == -1 { 172 | // zmq_send did not take ownership, free message 173 | C.zmq_msg_close(&m) 174 | return casterr(err) 175 | } 176 | return nil 177 | } 178 | 179 | // Receive a message from the socket. 180 | // int zmq_recv (void *s, zmq_msg_t *msg, int flags); 181 | func (s *Socket) Recv(flags SendRecvOption) (data []byte, err error) { 182 | // Allocate and initialise a new zmq_msg_t 183 | var m C.zmq_msg_t 184 | var rc C.int 185 | if rc, err = C.zmq_msg_init(&m); rc != 0 { 186 | err = casterr(err) 187 | return 188 | } 189 | defer C.zmq_msg_close(&m) 190 | // Receive into message 191 | if rc, err = C.zmq_recvmsg(s.s, &m, C.int(flags)); rc == -1 { 192 | err = casterr(err) 193 | return 194 | } 195 | err = nil 196 | // Copy message data into a byte array 197 | // FIXME Ideally this wouldn't require a copy. 198 | size := C.zmq_msg_size(&m) 199 | if size > 0 { 200 | data = C.GoBytes(C.zmq_msg_data(&m), C.int(size)) 201 | } else { 202 | data = nil 203 | } 204 | return 205 | } 206 | 207 | // Register a monitoring callback endpoint. 208 | // int zmq_socket_monitor (void *s, const char *addr, int events); 209 | func (s *Socket) Monitor(address string, events Event) error { 210 | a := C.CString(address) 211 | defer C.free(unsafe.Pointer(a)) 212 | 213 | rc, err := C.zmq_socket_monitor(s.apiSocket(), a, C.int(events)) 214 | if rc == -1 { 215 | return casterr(err) 216 | } 217 | return nil 218 | } 219 | 220 | // Portability helper 221 | func (s *Socket) getRcvmore() (more bool, err error) { 222 | value, err := s.GetSockOptInt(RCVMORE) 223 | more = value != 0 224 | return 225 | } 226 | 227 | // run a zmq_proxy with in, out and capture sockets 228 | func Proxy(in, out, capture *Socket) error { 229 | var c unsafe.Pointer 230 | if capture != nil { 231 | c = capture.apiSocket() 232 | } 233 | if rc, err := C.zmq_proxy(in.apiSocket(), out.apiSocket(), c); rc != 0 { 234 | return casterr(err) 235 | } 236 | return errors.New("zmq_proxy() returned unexpectedly.") 237 | } 238 | -------------------------------------------------------------------------------- /zmq_3_x_test.go: -------------------------------------------------------------------------------- 1 | // +build zmq_3_x zmq_4_x 2 | 3 | /* 4 | Copyright 2010 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | package gozmq 19 | 20 | import ( 21 | "errors" 22 | "testing" 23 | "time" 24 | ) 25 | 26 | const ADDR_PROXY_IN = "tcp://127.0.0.1:24114" 27 | const ADDR_PROXY_OUT = "tcp://127.0.0.1:24115" 28 | const ADDR_PROXY_CAP = "tcp://127.0.0.1:24116" 29 | 30 | func TestProxy(t *testing.T) { 31 | te1, te2 := NewTestEnv(t), NewTestEnv(t) 32 | exitOk := make(chan bool, 1) 33 | go func() { 34 | in := te1.NewBoundSocket(ROUTER, ADDR_PROXY_IN) 35 | out := te1.NewBoundSocket(DEALER, ADDR_PROXY_OUT) 36 | capture := te1.NewBoundSocket(PUSH, ADDR_PROXY_CAP) 37 | err := Proxy(in, out, capture) 38 | 39 | select { 40 | case <-exitOk: 41 | default: 42 | t.Error("Proxy() failed: ", err) 43 | } 44 | }() 45 | 46 | in := te2.NewConnectedSocket(REQ, ADDR_PROXY_IN) 47 | out := te2.NewConnectedSocket(REP, ADDR_PROXY_OUT) 48 | capture := te2.NewConnectedSocket(PULL, ADDR_PROXY_CAP) 49 | time.Sleep(1e8) 50 | te2.Send(in, nil, 0) 51 | te2.Recv(out, 0) 52 | te2.Recv(capture, 0) 53 | 54 | te2.Close() 55 | exitOk <- true 56 | te1.Close() 57 | } 58 | 59 | func TestProxyNoCapture(t *testing.T) { 60 | te1, te2 := NewTestEnv(t), NewTestEnv(t) 61 | exitOk := make(chan bool, 1) 62 | go func() { 63 | in := te1.NewBoundSocket(ROUTER, ADDR_PROXY_IN) 64 | out := te1.NewBoundSocket(DEALER, ADDR_PROXY_OUT) 65 | err := Proxy(in, out, nil) 66 | 67 | select { 68 | case <-exitOk: 69 | default: 70 | t.Error("Proxy() failed: ", err) 71 | } 72 | }() 73 | 74 | in := te2.NewConnectedSocket(REQ, ADDR_PROXY_IN) 75 | out := te2.NewConnectedSocket(REP, ADDR_PROXY_OUT) 76 | time.Sleep(1e8) 77 | te2.Send(in, nil, 0) 78 | te2.Recv(out, 0) 79 | 80 | te2.Close() 81 | exitOk <- true 82 | te1.Close() 83 | } 84 | 85 | func TestSocket_SetSockOptStringNil(t *testing.T) { 86 | failed := make(chan bool, 2) 87 | c, _ := NewContext() 88 | defer c.Close() 89 | go func() { 90 | srv, _ := c.NewSocket(REP) 91 | defer srv.Close() 92 | srv.SetSockOptString(TCP_ACCEPT_FILTER, "127.0.0.1") 93 | srv.SetSockOptString(TCP_ACCEPT_FILTER, "192.0.2.1") 94 | srv.Bind(ADDRESS1) // 127.0.0.1 and 192.0.2.1 are allowed here. 95 | // The test will fail if the following line is removed: 96 | srv.SetSockOptStringNil(TCP_ACCEPT_FILTER) 97 | srv.SetSockOptString(TCP_ACCEPT_FILTER, "192.0.2.2") 98 | srv.Bind(ADDRESS2) // Only 192.0.2.1 is allowed here. 99 | for { 100 | if _, err := srv.Recv(0); err != nil { 101 | break 102 | } 103 | srv.Send(nil, 0) 104 | } 105 | }() 106 | go func() { 107 | s2, _ := c.NewSocket(REQ) 108 | defer s2.Close() 109 | s2.SetSockOptInt(LINGER, 0) 110 | s2.Connect(ADDRESS2) 111 | s2.Send(nil, 0) 112 | if _, err := s2.Recv(0); err == nil { 113 | // 127.0.0.1 is supposed to be ignored by ADDRESS2: 114 | t.Error("SetSockOptStringNil did not clear TCP_ACCEPT_FILTER.") 115 | } 116 | failed <- true 117 | }() 118 | s1, _ := c.NewSocket(REQ) 119 | defer s1.Close() 120 | s1.Connect(ADDRESS1) 121 | s1.Send(nil, 0) 122 | s1.Recv(0) 123 | select { 124 | case <-failed: 125 | case <-time.After(50 * time.Millisecond): 126 | } 127 | } 128 | 129 | const ( 130 | TESTMONITOR_ADDR_SINK = "tcp://127.0.0.1:24117" 131 | TESTMONITOR_ADDR_EVENTS = "inproc://TestMonitorEvents" 132 | ) 133 | 134 | func TestMonitor(t *testing.T) { 135 | te := NewTestEnv(t) 136 | defer te.Close() 137 | 138 | // Prepare the sink socket. 139 | out := te.NewSocket(PULL) 140 | err := out.Bind(TESTMONITOR_ADDR_SINK) 141 | if err != nil { 142 | t.Fatal(err) 143 | } 144 | 145 | // Prepare the source socket, do not connect yet. 146 | in := te.NewSocket(PUSH) 147 | defer in.Close() 148 | 149 | // Attach the monitor. 150 | err = in.Monitor(TESTMONITOR_ADDR_EVENTS, 151 | EVENT_CONNECTED|EVENT_DISCONNECTED) 152 | if err != nil { 153 | out.Close() 154 | t.Fatal(err) 155 | } 156 | 157 | monitor := te.NewConnectedSocket(PAIR, TESTMONITOR_ADDR_EVENTS) 158 | 159 | // Connect the client to the server, wait for EVENT_CONNECTED. 160 | err = in.Connect(TESTMONITOR_ADDR_SINK) 161 | if err != nil { 162 | out.Close() 163 | t.Fatal(err) 164 | } 165 | 166 | err = waitForEvent(t, monitor) 167 | if err != nil { 168 | out.Close() 169 | t.Fatal(err) 170 | } 171 | 172 | // Close the sink socket, wait for EVENT_DISCONNECTED. 173 | err = out.Close() 174 | if err != nil { 175 | t.Fatal(err) 176 | } 177 | 178 | err = waitForEvent(t, monitor) 179 | if err != nil { 180 | t.Fatal(err) 181 | } 182 | } 183 | 184 | func waitForEvent(t *testing.T, monitor *Socket) error { 185 | exit := make(chan error, 1) 186 | 187 | // This goroutine will return either when an event is received 188 | // or the context is closed. 189 | go func() { 190 | // RecvMultipart should work for both zeromq3-x and libzmq API. 191 | _, ex := monitor.RecvMultipart(0) 192 | exit <- ex 193 | }() 194 | 195 | timeout := time.After(time.Second) 196 | 197 | select { 198 | case err := <-exit: 199 | return err 200 | case <-timeout: 201 | return errors.New("Test timed out") 202 | } 203 | 204 | return nil 205 | } 206 | -------------------------------------------------------------------------------- /zmq_4_x.go: -------------------------------------------------------------------------------- 1 | // +build zmq_4_x 2 | 3 | /* 4 | Copyright 2010-2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo pkg-config: libzmq 23 | #include 24 | #include 25 | #include 26 | */ 27 | import "C" 28 | 29 | const ( 30 | IPV6 = IntSocketOption(C.ZMQ_IPV6) 31 | IMMEDIATE = IntSocketOption(C.ZMQ_IMMEDIATE) 32 | MECHANISM = IntSocketOption(C.ZMQ_MECHANISM) 33 | PLAIN_SERVER = IntSocketOption(C.ZMQ_PLAIN_SERVER) 34 | PLAIN_USERNAME = StringSocketOption(C.ZMQ_PLAIN_USERNAME) 35 | PLAIN_PASSWORD = StringSocketOption(C.ZMQ_PLAIN_PASSWORD) 36 | CURVE_PUBLICKEY = StringSocketOption(C.ZMQ_CURVE_PUBLICKEY) 37 | CURVE_SECRETKEY = StringSocketOption(C.ZMQ_CURVE_SECRETKEY) 38 | CURVE_SERVERKEY = StringSocketOption(C.ZMQ_CURVE_SERVERKEY) 39 | ZAP_DOMAIN = StringSocketOption(C.ZMQ_ZAP_DOMAIN) 40 | ROUTER_RAW = IntSocketOption(C.ZMQ_ROUTER_RAW) 41 | PROBE_ROUTER = IntSocketOption(C.ZMQ_PROBE_ROUTER) 42 | REQ_CORRELATE = IntSocketOption(C.ZMQ_REQ_CORRELATE) 43 | REQ_RELAXED = IntSocketOption(C.ZMQ_REQ_RELAXED) 44 | CURVE_SERVER = IntSocketOption(C.ZMQ_CURVE_SERVER) 45 | CONFLATE = IntSocketOption(C.ZMQ_CONFLATE) 46 | ) 47 | -------------------------------------------------------------------------------- /zmq_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2010 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package gozmq 17 | 18 | import ( 19 | "log" 20 | "runtime" 21 | "syscall" 22 | "testing" 23 | "time" 24 | ) 25 | 26 | const ADDRESS1 = "tcp://127.0.0.1:23456" 27 | const ADDRESS2 = "tcp://127.0.0.1:23457" 28 | const ADDRESS3 = "tcp://127.0.0.1:23458" 29 | 30 | // Addresses for the device test. These cannot be reused since the device 31 | // will keep running after the test terminates 32 | const ADDR_DEV_IN = "tcp://127.0.0.1:24111" 33 | const ADDR_DEV_OUT = "tcp://127.0.0.1:24112" 34 | 35 | // a process local address 36 | const ADDRESS_INPROC = "inproc://test" 37 | 38 | const SERVER_READY = "SERVER READY" 39 | 40 | func runServer(t *testing.T, c *Context, callback func(s *Socket)) chan bool { 41 | finished := make(chan bool) 42 | go func() { 43 | runtime.LockOSThread() 44 | defer runtime.UnlockOSThread() 45 | s, _ := c.NewSocket(REP) 46 | defer s.Close() 47 | if rc := s.Bind(ADDRESS1); rc != nil { 48 | t.Errorf("Failed to bind to %s; %s", ADDRESS1, rc.Error()) 49 | } 50 | callback(s) 51 | finished <- true 52 | }() 53 | return finished 54 | } 55 | 56 | func runPollServer(t *testing.T) (done, bound chan bool) { 57 | done = make(chan bool) 58 | bound = make(chan bool) 59 | go func() { 60 | te := NewTestEnv(t) 61 | defer te.Close() 62 | s1 := te.NewBoundSocket(REP, ADDRESS1) 63 | s2 := te.NewBoundSocket(REP, ADDRESS2) 64 | s3 := te.NewBoundSocket(REP, ADDRESS3) 65 | 66 | pi := PollItems{ 67 | PollItem{Socket: s1, Events: POLLIN}, 68 | PollItem{Socket: s2, Events: POLLIN}, 69 | PollItem{Socket: s3, Events: POLLIN}, 70 | } 71 | bound <- true 72 | 73 | sent := 0 74 | for { 75 | _, err := Poll(pi, -1) 76 | if err != nil { 77 | done <- false 78 | return 79 | } 80 | 81 | switch { 82 | case pi[0].REvents&POLLIN != 0: 83 | pi[0].Socket.Recv(0) // eat the incoming message 84 | pi[0].Socket.Send(nil, 0) 85 | sent++ 86 | case pi[1].REvents&POLLIN != 0: 87 | pi[1].Socket.Recv(0) // eat the incoming message 88 | pi[1].Socket.Send(nil, 0) 89 | sent++ 90 | case pi[2].REvents&POLLIN != 0: 91 | pi[2].Socket.Recv(0) // eat the incoming message 92 | pi[2].Socket.Send(nil, 0) 93 | sent++ 94 | } 95 | 96 | if sent == 3 { 97 | break 98 | } 99 | } 100 | 101 | done <- true 102 | }() 103 | return 104 | } 105 | 106 | func TestVersion(t *testing.T) { 107 | major, minor, patch := Version() 108 | // Require at least 2.0.9 109 | if major > 2 && minor >= 0 && patch >= 9 { 110 | t.Errorf("expected at least 0mq version 2.0.9") 111 | } 112 | } 113 | 114 | func TestCreateDestroyContext(t *testing.T) { 115 | c, _ := NewContext() 116 | c.Close() 117 | c, _ = NewContext() 118 | c.Close() 119 | } 120 | 121 | func TestContext_IOThreads(t *testing.T) { 122 | c, _ := NewContext() 123 | defer c.Close() 124 | if iothreads, err := c.IOThreads(); err != nil { 125 | t.Fatalf("Failed to get IO_THREADS: %s", err.Error()) 126 | } else if iothreads != 1 { 127 | t.Fatalf("Got IO_THREADS = %s", iothreads) 128 | } 129 | } 130 | 131 | func TestContext_SetIOThreads(t *testing.T) { 132 | c, _ := NewContext() 133 | defer c.Close() 134 | if err := c.SetIOThreads(2); err != nil { 135 | t.Fatalf("Failed to set IO_THREADS: %s", err.Error()) 136 | } 137 | if iothreads, err := c.IOThreads(); err != nil { 138 | t.Fatalf("Failed to get IO_THREADS: %s", err.Error()) 139 | } else if iothreads != 2 { 140 | t.Fatalf("Got IO_THREADS = %s", iothreads) 141 | } 142 | } 143 | 144 | func TestSocket_Connect(t *testing.T) { 145 | c, _ := NewContext() 146 | defer c.Close() 147 | s, _ := c.NewSocket(REP) 148 | defer s.Close() 149 | if rc := s.Connect(ADDRESS1); rc != nil { 150 | t.Errorf("Failed to bind to %s; %s", ADDRESS1, rc.Error()) 151 | } 152 | bad_address := "a malformed address" 153 | rc := s.Connect(bad_address) 154 | switch rc { 155 | case syscall.EINVAL: //pass 156 | case nil: 157 | t.Errorf("Connected to %s", bad_address) 158 | default: 159 | t.Errorf("Received incorrect error connecting to %s; %s", bad_address, rc.Error()) 160 | } 161 | s.Close() 162 | rc = s.Connect(ADDRESS1) 163 | switch rc { 164 | case ENOTSOCK: //pass 165 | case nil: 166 | t.Errorf("Connected a closed socket") 167 | default: 168 | t.Errorf("Expected ENOTSOCK, got %T(%d); %s", rc, rc, rc.Error()) 169 | } 170 | } 171 | 172 | func TestBindToLoopBack(t *testing.T) { 173 | c, _ := NewContext() 174 | defer c.Close() 175 | s, _ := c.NewSocket(REP) 176 | defer s.Close() 177 | if rc := s.Bind(ADDRESS1); rc != nil { 178 | t.Errorf("Failed to bind to %s; %s", ADDRESS1, rc.Error()) 179 | } 180 | } 181 | 182 | func TestSetSockOptInt(t *testing.T) { 183 | c, _ := NewContext() 184 | defer c.Close() 185 | s, _ := c.NewSocket(REQ) 186 | defer s.Close() 187 | var linger int = 42 188 | if rc := s.SetSockOptInt(LINGER, linger); rc != nil { 189 | t.Errorf("Failed to set linger; %v", rc) 190 | } 191 | if val, rc := s.GetSockOptInt(LINGER); rc != nil { 192 | t.Errorf("Failed to get linger; %v", rc) 193 | } else if val != linger { 194 | t.Errorf("Expected %d, got %d", linger, val) 195 | } 196 | } 197 | 198 | func TestSetSockOptString(t *testing.T) { 199 | c, _ := NewContext() 200 | defer c.Close() 201 | s, _ := c.NewSocket(SUB) 202 | defer s.Close() 203 | if rc := s.Bind(ADDRESS1); rc != nil { 204 | t.Errorf("Failed to bind to %s; %s", ADDRESS1, rc.Error()) 205 | } 206 | if rc := s.SetSockOptString(SUBSCRIBE, "TEST"); rc != nil { 207 | t.Errorf("Failed to subscribe; %v", rc) 208 | } 209 | if rc := s.SetSubscribe("TEST"); rc != nil { 210 | t.Errorf("Failed to subscribe; %v", rc) 211 | } 212 | if rc := s.SetUnsubscribe("TEST"); rc != nil { 213 | t.Errorf("Failed to unsubscribe; %v", rc) 214 | } 215 | } 216 | 217 | func TestMultipart(t *testing.T) { 218 | c, _ := NewContext() 219 | defer c.Close() 220 | finished := runServer(t, c, func(s *Socket) { 221 | parts, rc := s.RecvMultipart(0) 222 | if rc != nil { 223 | t.Errorf("Failed to receive multipart message; %s", rc.Error()) 224 | } 225 | if len(parts) != 2 { 226 | t.Errorf("Invalid multipart message, not enough parts; %d", len(parts)) 227 | } 228 | if string(parts[0]) != "part1" || string(parts[1]) != "part2" { 229 | t.Errorf("Invalid multipart message.") 230 | } 231 | }) 232 | 233 | s, _ := c.NewSocket(REQ) 234 | defer s.Close() 235 | if rc := s.Connect(ADDRESS1); rc != nil { 236 | t.Errorf("Failed to connect to %s; %s", ADDRESS1, rc.Error()) 237 | } 238 | if rc := s.SendMultipart([][]byte{[]byte("part1"), []byte("part2")}, 0); rc != nil { 239 | t.Errorf("Failed to send multipart message; %s", rc.Error()) 240 | } 241 | <-finished 242 | } 243 | 244 | func TestPoll(t *testing.T) { 245 | te := NewTestEnv(t) 246 | defer te.Close() 247 | finished, bound := runPollServer(t) 248 | 249 | // wait for sockets to bind 250 | <-bound 251 | 252 | for _, addr := range []string{ADDRESS2, ADDRESS3, ADDRESS1} { 253 | sock := te.NewConnectedSocket(REQ, addr) 254 | te.Send(sock, []byte("request data"), 0) 255 | te.Recv(sock, 0) 256 | } 257 | 258 | <-finished 259 | 260 | } 261 | 262 | func TestDevice(t *testing.T) { 263 | go func() { 264 | // the device will never exit so this goroutine will never terminate 265 | te := NewTestEnv(t) 266 | defer te.Close() 267 | in := te.NewBoundSocket(PULL, ADDR_DEV_IN) 268 | out := te.NewBoundSocket(PUSH, ADDR_DEV_OUT) 269 | err := Device(STREAMER, in, out) 270 | 271 | // Should never get to here 272 | t.Error("Device() failed: ", err) 273 | }() 274 | 275 | te := NewTestEnv(t) 276 | defer te.Close() 277 | out := te.NewConnectedSocket(PUSH, ADDR_DEV_IN) 278 | in := te.NewConnectedSocket(PULL, ADDR_DEV_OUT) 279 | 280 | time.Sleep(1e8) 281 | 282 | te.Send(out, nil, 0) 283 | te.Recv(in, 0) 284 | } 285 | 286 | func TestZmqErrorStr(t *testing.T) { 287 | var e error = EFSM 288 | es := e.Error() 289 | if es != "Operation cannot be accomplished in current state" { 290 | t.Errorf("EFSM.String() returned unexpected result: %s", e) 291 | } 292 | } 293 | 294 | func TestZmqErrorComparison(t *testing.T) { 295 | var e error = getErrorForTesting() 296 | if e != EFSM { 297 | t.Errorf("EFSM did not compare correctly. This should not happen.") 298 | } 299 | } 300 | 301 | // expensive test - send a huge amount of data. should be enough to 302 | // trash a current machine if Send or Recv are leaking. 303 | /* 304 | func TestMessageMemory(t *testing.T) { 305 | // primarily to see if Send or Recv are leaking memory 306 | 307 | const MSG_SIZE = 1e6 308 | const MSG_COUNT = 100 * 1000 309 | 310 | te := NewTestEnv(nil) 311 | defer te.Close() 312 | 313 | data := make([]byte, MSG_SIZE) 314 | 315 | out := te.NewBoundSocket(PUSH, ADDRESS1) 316 | in := te.NewConnectedSocket(PULL, ADDRESS1) 317 | 318 | for i := 0; i < MSG_COUNT; i++ { 319 | te.Send(out, data, 0) 320 | d2 := te.Recv(in, 0) 321 | if len(d2) != MSG_SIZE { 322 | t.Errorf("Bad message size received") 323 | } 324 | } 325 | } 326 | */ 327 | 328 | func doBenchmarkSendReceive(b *testing.B, size int, addr string) { 329 | // since this is a benchmark it should probably call 330 | // this package's api functions directly rather than 331 | // using the testEnv wrappers 332 | b.StopTimer() 333 | data := make([]byte, size) 334 | 335 | te := NewTestEnv(nil) 336 | defer te.Close() 337 | b.StartTimer() 338 | 339 | out := te.NewBoundSocket(PUSH, ADDRESS1) 340 | in := te.NewConnectedSocket(PULL, ADDRESS1) 341 | 342 | for i := 0; i < b.N; i++ { 343 | te.Send(out, data, 0) 344 | d2 := te.Recv(in, 0) 345 | if len(d2) != size { 346 | panic("Bad message size received") 347 | } 348 | } 349 | } 350 | 351 | func BenchmarkSendReceive1Btcp(b *testing.B) { 352 | doBenchmarkSendReceive(b, 1, ADDRESS1) 353 | } 354 | 355 | func BenchmarkSendReceive1KBtcp(b *testing.B) { 356 | doBenchmarkSendReceive(b, 1e3, ADDRESS1) 357 | } 358 | 359 | func BenchmarkSendReceive1MBtcp(b *testing.B) { 360 | doBenchmarkSendReceive(b, 1e6, ADDRESS1) 361 | } 362 | 363 | func BenchmarkSendReceive1Binproc(b *testing.B) { 364 | doBenchmarkSendReceive(b, 1, ADDRESS_INPROC) 365 | } 366 | 367 | func BenchmarkSendReceive1KBinproc(b *testing.B) { 368 | doBenchmarkSendReceive(b, 1e3, ADDRESS_INPROC) 369 | } 370 | 371 | func BenchmarkSendReceive1MBinproc(b *testing.B) { 372 | doBenchmarkSendReceive(b, 1e6, ADDRESS_INPROC) 373 | } 374 | 375 | // A helper to make tests less verbose 376 | type testEnv struct { 377 | context *Context 378 | sockets []*Socket 379 | t *testing.T 380 | } 381 | 382 | func NewTestEnv(t *testing.T) *testEnv { 383 | // Encapsulate everything, including (unnecessarily) the context 384 | // in the same thread. 385 | runtime.LockOSThread() 386 | c, err := NewContext() 387 | if err != nil { 388 | t.Errorf("failed to create context in testEnv: %v", err) 389 | t.FailNow() 390 | } 391 | return &testEnv{context: c, t: t} 392 | } 393 | 394 | func (te *testEnv) NewSocket(t SocketType) *Socket { 395 | s, err := te.context.NewSocket(t) 396 | if err != nil { 397 | log.Panicf("Failed to Create socket of type %v: %v", t, err) 398 | } 399 | return s 400 | } 401 | 402 | func (te *testEnv) NewBoundSocket(t SocketType, bindAddr string) *Socket { 403 | s := te.NewSocket(t) 404 | if err := s.Bind(bindAddr); err != nil { 405 | log.Panicf("Failed to connect to %v: %v", bindAddr, err) 406 | } 407 | te.pushSocket(s) 408 | return s 409 | } 410 | 411 | func (te *testEnv) NewConnectedSocket(t SocketType, connectAddr string) *Socket { 412 | s := te.NewSocket(t) 413 | if err := s.Connect(connectAddr); err != nil { 414 | log.Panicf("Failed to connect to %v: %v", connectAddr, err) 415 | } 416 | te.pushSocket(s) 417 | return s 418 | } 419 | 420 | func (te *testEnv) pushSocket(s *Socket) { 421 | te.sockets = append(te.sockets, s) 422 | } 423 | 424 | func (te *testEnv) Close() { 425 | if err := recover(); err != nil { 426 | te.t.Errorf("failed in testEnv: %v", err) 427 | } 428 | 429 | for _, s := range te.sockets { 430 | s.Close() 431 | } 432 | 433 | if te.context != nil { 434 | te.context.Close() 435 | } 436 | runtime.UnlockOSThread() 437 | } 438 | 439 | func (te *testEnv) Send(sock *Socket, data []byte, flags SendRecvOption) { 440 | if err := sock.Send(data, flags); err != nil { 441 | te.t.Errorf("Send failed") 442 | } 443 | } 444 | 445 | func (te *testEnv) Recv(sock *Socket, flags SendRecvOption) []byte { 446 | data, err := sock.Recv(flags) 447 | if err != nil { 448 | te.t.Errorf("Receive failed") 449 | } 450 | return data 451 | } 452 | 453 | // TODO Test various socket types. UDP, TCP, etc. 454 | // TODO Test NOBLOCK mode. 455 | // TODO Test getting/setting socket options. Probably sufficient to do just one 456 | // int and one string test. 457 | 458 | // TODO Test that closing a context underneath a socket behaves "reasonably" (ie. doesnt' crash). 459 | -------------------------------------------------------------------------------- /zmq_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd linux netbsd openbsd 2 | 3 | /* 4 | Copyright 2012 Alec Thomas 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package gozmq 20 | 21 | /* 22 | #cgo pkg-config: libzmq 23 | #include 24 | */ 25 | import "C" 26 | 27 | type ZmqOsSocketType C.int 28 | 29 | func (self ZmqOsSocketType) ToRaw() C.int { 30 | return C.int(self) 31 | } 32 | -------------------------------------------------------------------------------- /zmq_windows.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2012 Alec Thomas 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package gozmq 18 | 19 | /* 20 | #cgo pkg-config: libzmq 21 | #include 22 | */ 23 | import "C" 24 | 25 | type ZmqOsSocketType C.SOCKET 26 | 27 | func (self ZmqOsSocketType) ToRaw() C.SOCKET { 28 | return C.SOCKET(self) 29 | } 30 | -------------------------------------------------------------------------------- /zmqgen_2_1.go: -------------------------------------------------------------------------------- 1 | // +build zmq_2_1 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message parts to follow. 24 | // 25 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptUInt64(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_HWM: Retrieve high water mark. 33 | // 34 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) HWM() (uint64, error) { 37 | return s.GetSockOptUInt64(HWM) 38 | } 39 | 40 | // ZMQ_SWAP: Retrieve disk offload size. 41 | // 42 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) Swap() (int64, error) { 45 | return s.GetSockOptInt64(SWAP) 46 | } 47 | 48 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 49 | // 50 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc7 51 | // 52 | func (s *Socket) Affinity() (uint64, error) { 53 | return s.GetSockOptUInt64(AFFINITY) 54 | } 55 | 56 | // ZMQ_IDENTITY: Retrieve socket identity. 57 | // 58 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc8 59 | // 60 | func (s *Socket) Identity() (string, error) { 61 | return s.GetSockOptString(IDENTITY) 62 | } 63 | 64 | // ZMQ_RATE: Retrieve multicast data rate. 65 | // 66 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc9 67 | // 68 | func (s *Socket) Rate() (int64, error) { 69 | return s.GetSockOptInt64(RATE) 70 | } 71 | 72 | // ZMQ_RECOVERY_IVL_MSEC: Get multicast recovery interval in milliseconds. 73 | // 74 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc11 75 | // 76 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 77 | ms, err := s.GetSockOptInt64(RECOVERY_IVL_MSEC) 78 | return time.Duration(ms) * time.Millisecond, err 79 | } 80 | 81 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 82 | // 83 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc12 84 | // 85 | func (s *Socket) McastLoop() (bool, error) { 86 | value, err := s.GetSockOptInt64(MCAST_LOOP) 87 | return value != 0, err 88 | } 89 | 90 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 91 | // 92 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc13 93 | // 94 | func (s *Socket) SndBuf() (uint64, error) { 95 | return s.GetSockOptUInt64(SNDBUF) 96 | } 97 | 98 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 99 | // 100 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc14 101 | // 102 | func (s *Socket) RcvBuf() (uint64, error) { 103 | return s.GetSockOptUInt64(RCVBUF) 104 | } 105 | 106 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 107 | // 108 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc15 109 | // 110 | func (s *Socket) Linger() (time.Duration, error) { 111 | ms, err := s.GetSockOptInt(LINGER) 112 | return time.Duration(ms) * time.Millisecond, err 113 | } 114 | 115 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 116 | // 117 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc16 118 | // 119 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 120 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 121 | return time.Duration(ms) * time.Millisecond, err 122 | } 123 | 124 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 125 | // 126 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc17 127 | // 128 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 129 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 130 | return time.Duration(ms) * time.Millisecond, err 131 | } 132 | 133 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 134 | // 135 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc18 136 | // 137 | func (s *Socket) Backlog() (int, error) { 138 | return s.GetSockOptInt(BACKLOG) 139 | } 140 | 141 | // ZMQ_EVENTS: Retrieve socket event state. 142 | // 143 | // See: http://api.zeromq.org/2.1:zmq-getsockopt#toc20 144 | // 145 | func (s *Socket) Events() (uint64, error) { 146 | return s.GetSockOptUInt64(EVENTS) 147 | } 148 | 149 | // Socket Option Setters 150 | 151 | // ZMQ_HWM: Set high water mark. 152 | // 153 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc3 154 | // 155 | func (s *Socket) SetHWM(value uint64) error { 156 | return s.SetSockOptUInt64(HWM, value) 157 | } 158 | 159 | // ZMQ_SWAP: Set disk offload size. 160 | // 161 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc4 162 | // 163 | func (s *Socket) SetSwap(value int64) error { 164 | return s.SetSockOptInt64(SWAP, value) 165 | } 166 | 167 | // ZMQ_AFFINITY: Set I/O thread affinity. 168 | // 169 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc5 170 | // 171 | func (s *Socket) SetAffinity(value uint64) error { 172 | return s.SetSockOptUInt64(AFFINITY, value) 173 | } 174 | 175 | // ZMQ_IDENTITY: Set socket identity. 176 | // 177 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc6 178 | // 179 | func (s *Socket) SetIdentity(value string) error { 180 | return s.SetSockOptString(IDENTITY, value) 181 | } 182 | 183 | // ZMQ_SUBSCRIBE: Establish message filter. 184 | // 185 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc7 186 | // 187 | func (s *Socket) SetSubscribe(value string) error { 188 | return s.SetSockOptString(SUBSCRIBE, value) 189 | } 190 | 191 | // ZMQ_UNSUBSCRIBE: Remove message filter. 192 | // 193 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc8 194 | // 195 | func (s *Socket) SetUnsubscribe(value string) error { 196 | return s.SetSockOptString(UNSUBSCRIBE, value) 197 | } 198 | 199 | // ZMQ_RATE: Set multicast data rate. 200 | // 201 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc9 202 | // 203 | func (s *Socket) SetRate(value int64) error { 204 | return s.SetSockOptInt64(RATE, value) 205 | } 206 | 207 | // ZMQ_RECOVERY_IVL_MSEC: Set multicast recovery interval in milliseconds. 208 | // 209 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc11 210 | // 211 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 212 | return s.SetSockOptInt64(RECOVERY_IVL_MSEC, int64(value/time.Millisecond)) 213 | } 214 | 215 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 216 | // 217 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc12 218 | // 219 | func (s *Socket) SetMcastLoop(value bool) error { 220 | if value { 221 | return s.SetSockOptInt64(MCAST_LOOP, 1) 222 | } 223 | return s.SetSockOptInt64(MCAST_LOOP, 0) 224 | } 225 | 226 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 227 | // 228 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc13 229 | // 230 | func (s *Socket) SetSndBuf(value uint64) error { 231 | return s.SetSockOptUInt64(SNDBUF, value) 232 | } 233 | 234 | // ZMQ_RCVBUF: Set kernel receive buffer size. 235 | // 236 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc14 237 | // 238 | func (s *Socket) SetRcvBuf(value uint64) error { 239 | return s.SetSockOptUInt64(RCVBUF, value) 240 | } 241 | 242 | // ZMQ_LINGER: Set linger period for socket shutdown. 243 | // 244 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc15 245 | // 246 | func (s *Socket) SetLinger(value time.Duration) error { 247 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 248 | } 249 | 250 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 251 | // 252 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc16 253 | // 254 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 255 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 256 | } 257 | 258 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 259 | // 260 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc17 261 | // 262 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 263 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 264 | } 265 | 266 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 267 | // 268 | // See: http://api.zeromq.org/2.1:zmq-setsockopt#toc18 269 | // 270 | func (s *Socket) SetBacklog(value int) error { 271 | return s.SetSockOptInt(BACKLOG, value) 272 | } 273 | -------------------------------------------------------------------------------- /zmqgen_2_2.go: -------------------------------------------------------------------------------- 1 | // +build !zmq_2_1,!zmq_3_x,!zmq_4_x 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message parts to follow. 24 | // 25 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptUInt64(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_HWM: Retrieve high water mark. 33 | // 34 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) HWM() (uint64, error) { 37 | return s.GetSockOptUInt64(HWM) 38 | } 39 | 40 | // ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN. 41 | // 42 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) RcvTimeout() (time.Duration, error) { 45 | ms, err := s.GetSockOptInt(RCVTIMEO) 46 | return time.Duration(ms) * time.Millisecond, err 47 | } 48 | 49 | // ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN. 50 | // 51 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc7 52 | // 53 | func (s *Socket) SndTimeout() (time.Duration, error) { 54 | ms, err := s.GetSockOptInt(SNDTIMEO) 55 | return time.Duration(ms) * time.Millisecond, err 56 | } 57 | 58 | // ZMQ_SWAP: Retrieve disk offload size. 59 | // 60 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc8 61 | // 62 | func (s *Socket) Swap() (int64, error) { 63 | return s.GetSockOptInt64(SWAP) 64 | } 65 | 66 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 67 | // 68 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc9 69 | // 70 | func (s *Socket) Affinity() (uint64, error) { 71 | return s.GetSockOptUInt64(AFFINITY) 72 | } 73 | 74 | // ZMQ_IDENTITY: Retrieve socket identity. 75 | // 76 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc10 77 | // 78 | func (s *Socket) Identity() (string, error) { 79 | return s.GetSockOptString(IDENTITY) 80 | } 81 | 82 | // ZMQ_RATE: Retrieve multicast data rate. 83 | // 84 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc11 85 | // 86 | func (s *Socket) Rate() (int64, error) { 87 | return s.GetSockOptInt64(RATE) 88 | } 89 | 90 | // ZMQ_RECOVERY_IVL_MSEC: Get multicast recovery interval in milliseconds. 91 | // 92 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc13 93 | // 94 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 95 | ms, err := s.GetSockOptInt64(RECOVERY_IVL_MSEC) 96 | return time.Duration(ms) * time.Millisecond, err 97 | } 98 | 99 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 100 | // 101 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc14 102 | // 103 | func (s *Socket) McastLoop() (bool, error) { 104 | value, err := s.GetSockOptInt64(MCAST_LOOP) 105 | return value != 0, err 106 | } 107 | 108 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 109 | // 110 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc15 111 | // 112 | func (s *Socket) SndBuf() (uint64, error) { 113 | return s.GetSockOptUInt64(SNDBUF) 114 | } 115 | 116 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 117 | // 118 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc16 119 | // 120 | func (s *Socket) RcvBuf() (uint64, error) { 121 | return s.GetSockOptUInt64(RCVBUF) 122 | } 123 | 124 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 125 | // 126 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc17 127 | // 128 | func (s *Socket) Linger() (time.Duration, error) { 129 | ms, err := s.GetSockOptInt(LINGER) 130 | return time.Duration(ms) * time.Millisecond, err 131 | } 132 | 133 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 134 | // 135 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc18 136 | // 137 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 138 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 139 | return time.Duration(ms) * time.Millisecond, err 140 | } 141 | 142 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 143 | // 144 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc19 145 | // 146 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 147 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 148 | return time.Duration(ms) * time.Millisecond, err 149 | } 150 | 151 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 152 | // 153 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc20 154 | // 155 | func (s *Socket) Backlog() (int, error) { 156 | return s.GetSockOptInt(BACKLOG) 157 | } 158 | 159 | // ZMQ_EVENTS: Retrieve socket event state. 160 | // 161 | // See: http://api.zeromq.org/2.2:zmq-getsockopt#toc22 162 | // 163 | func (s *Socket) Events() (uint64, error) { 164 | return s.GetSockOptUInt64(EVENTS) 165 | } 166 | 167 | // Socket Option Setters 168 | 169 | // ZMQ_HWM: Set high water mark. 170 | // 171 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc3 172 | // 173 | func (s *Socket) SetHWM(value uint64) error { 174 | return s.SetSockOptUInt64(HWM, value) 175 | } 176 | 177 | // ZMQ_SWAP: Set disk offload size. 178 | // 179 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc4 180 | // 181 | func (s *Socket) SetSwap(value int64) error { 182 | return s.SetSockOptInt64(SWAP, value) 183 | } 184 | 185 | // ZMQ_AFFINITY: Set I/O thread affinity. 186 | // 187 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc5 188 | // 189 | func (s *Socket) SetAffinity(value uint64) error { 190 | return s.SetSockOptUInt64(AFFINITY, value) 191 | } 192 | 193 | // ZMQ_IDENTITY: Set socket identity. 194 | // 195 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc6 196 | // 197 | func (s *Socket) SetIdentity(value string) error { 198 | return s.SetSockOptString(IDENTITY, value) 199 | } 200 | 201 | // ZMQ_SUBSCRIBE: Establish message filter. 202 | // 203 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc7 204 | // 205 | func (s *Socket) SetSubscribe(value string) error { 206 | return s.SetSockOptString(SUBSCRIBE, value) 207 | } 208 | 209 | // ZMQ_UNSUBSCRIBE: Remove message filter. 210 | // 211 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc8 212 | // 213 | func (s *Socket) SetUnsubscribe(value string) error { 214 | return s.SetSockOptString(UNSUBSCRIBE, value) 215 | } 216 | 217 | // ZMQ_RCVTIMEO: Maximum time before a recv operation returns with EAGAIN. 218 | // 219 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc9 220 | // 221 | func (s *Socket) SetRcvTimeout(value time.Duration) error { 222 | return s.SetSockOptInt(RCVTIMEO, int(value/time.Millisecond)) 223 | } 224 | 225 | // ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN. 226 | // 227 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc10 228 | // 229 | func (s *Socket) SetSndTimeout(value time.Duration) error { 230 | return s.SetSockOptInt(SNDTIMEO, int(value/time.Millisecond)) 231 | } 232 | 233 | // ZMQ_RATE: Set multicast data rate. 234 | // 235 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc11 236 | // 237 | func (s *Socket) SetRate(value int64) error { 238 | return s.SetSockOptInt64(RATE, value) 239 | } 240 | 241 | // ZMQ_RECOVERY_IVL_MSEC: Set multicast recovery interval in milliseconds. 242 | // 243 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc13 244 | // 245 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 246 | return s.SetSockOptInt64(RECOVERY_IVL_MSEC, int64(value/time.Millisecond)) 247 | } 248 | 249 | // ZMQ_MCAST_LOOP: Control multicast loop-back. 250 | // 251 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc14 252 | // 253 | func (s *Socket) SetMcastLoop(value bool) error { 254 | if value { 255 | return s.SetSockOptInt64(MCAST_LOOP, 1) 256 | } 257 | return s.SetSockOptInt64(MCAST_LOOP, 0) 258 | } 259 | 260 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 261 | // 262 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc15 263 | // 264 | func (s *Socket) SetSndBuf(value uint64) error { 265 | return s.SetSockOptUInt64(SNDBUF, value) 266 | } 267 | 268 | // ZMQ_RCVBUF: Set kernel receive buffer size. 269 | // 270 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc16 271 | // 272 | func (s *Socket) SetRcvBuf(value uint64) error { 273 | return s.SetSockOptUInt64(RCVBUF, value) 274 | } 275 | 276 | // ZMQ_LINGER: Set linger period for socket shutdown. 277 | // 278 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc17 279 | // 280 | func (s *Socket) SetLinger(value time.Duration) error { 281 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 282 | } 283 | 284 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 285 | // 286 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc18 287 | // 288 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 289 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 290 | } 291 | 292 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 293 | // 294 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc19 295 | // 296 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 297 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 298 | } 299 | 300 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 301 | // 302 | // See: http://api.zeromq.org/2.2:zmq-setsockopt#toc20 303 | // 304 | func (s *Socket) SetBacklog(value int) error { 305 | return s.SetSockOptInt(BACKLOG, value) 306 | } 307 | -------------------------------------------------------------------------------- /zmqgen_3_2.go: -------------------------------------------------------------------------------- 1 | // +build zmq_3_x 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message data parts to follow. 24 | // 25 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptInt(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_SNDHWM: Retrieves high water mark for outbound messages. 33 | // 34 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) SndHWM() (int, error) { 37 | return s.GetSockOptInt(SNDHWM) 38 | } 39 | 40 | // ZMQ_RCVHWM: Retrieve high water mark for inbound messages. 41 | // 42 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) RcvHWM() (int, error) { 45 | return s.GetSockOptInt(RCVHWM) 46 | } 47 | 48 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 49 | // 50 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc7 51 | // 52 | func (s *Socket) Affinity() (uint64, error) { 53 | return s.GetSockOptUInt64(AFFINITY) 54 | } 55 | 56 | // ZMQ_IDENTITY: Set socket identity. 57 | // 58 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc8 59 | // 60 | func (s *Socket) Identity() (string, error) { 61 | return s.GetSockOptString(IDENTITY) 62 | } 63 | 64 | // ZMQ_RATE: Retrieve multicast data rate. 65 | // 66 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc9 67 | // 68 | func (s *Socket) Rate() (int64, error) { 69 | return s.GetSockOptInt64(RATE) 70 | } 71 | 72 | // ZMQ_RECOVERY_IVL: Get multicast recovery interval. 73 | // 74 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc10 75 | // 76 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 77 | ms, err := s.GetSockOptInt64(RECOVERY_IVL) 78 | return time.Duration(ms) * time.Millisecond, err 79 | } 80 | 81 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 82 | // 83 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc11 84 | // 85 | func (s *Socket) SndBuf() (uint64, error) { 86 | return s.GetSockOptUInt64(SNDBUF) 87 | } 88 | 89 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 90 | // 91 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc12 92 | // 93 | func (s *Socket) RcvBuf() (uint64, error) { 94 | return s.GetSockOptUInt64(RCVBUF) 95 | } 96 | 97 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 98 | // 99 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc13 100 | // 101 | func (s *Socket) Linger() (time.Duration, error) { 102 | ms, err := s.GetSockOptInt(LINGER) 103 | return time.Duration(ms) * time.Millisecond, err 104 | } 105 | 106 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 107 | // 108 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc14 109 | // 110 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 111 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 112 | return time.Duration(ms) * time.Millisecond, err 113 | } 114 | 115 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 116 | // 117 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc15 118 | // 119 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 120 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 121 | return time.Duration(ms) * time.Millisecond, err 122 | } 123 | 124 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 125 | // 126 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc16 127 | // 128 | func (s *Socket) Backlog() (int, error) { 129 | return s.GetSockOptInt(BACKLOG) 130 | } 131 | 132 | // ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size. 133 | // 134 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc17 135 | // 136 | func (s *Socket) MaxMsgSize() (int64, error) { 137 | return s.GetSockOptInt64(MAXMSGSIZE) 138 | } 139 | 140 | // ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN. 141 | // 142 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc19 143 | // 144 | func (s *Socket) RcvTimeout() (time.Duration, error) { 145 | ms, err := s.GetSockOptInt(RCVTIMEO) 146 | return time.Duration(ms) * time.Millisecond, err 147 | } 148 | 149 | // ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN. 150 | // 151 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc20 152 | // 153 | func (s *Socket) SndTimeout() (time.Duration, error) { 154 | ms, err := s.GetSockOptInt(SNDTIMEO) 155 | return time.Duration(ms) * time.Millisecond, err 156 | } 157 | 158 | // ZMQ_IPV4ONLY: Retrieve IPv4-only socket override status. 159 | // 160 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc21 161 | // 162 | func (s *Socket) IPv4Only() (bool, error) { 163 | value, err := s.GetSockOptInt(IPV4ONLY) 164 | return value != 0, err 165 | } 166 | 167 | // ZMQ_DELAY_ATTACH_ON_CONNECT: Retrieve attach-on-connect value. 168 | // 169 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc22 170 | // 171 | func (s *Socket) DelayAttachOnConnect() (bool, error) { 172 | value, err := s.GetSockOptInt(DELAY_ATTACH_ON_CONNECT) 173 | return value != 0, err 174 | } 175 | 176 | // ZMQ_EVENTS: Retrieve socket event state. 177 | // 178 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc24 179 | // 180 | func (s *Socket) Events() (uint64, error) { 181 | return s.GetSockOptUInt64(EVENTS) 182 | } 183 | 184 | // ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 185 | // 186 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc26 187 | // 188 | func (s *Socket) TCPKeepalive() (int, error) { 189 | return s.GetSockOptInt(TCP_KEEPALIVE) 190 | } 191 | 192 | // ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS). 193 | // 194 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc27 195 | // 196 | func (s *Socket) TCPKeepaliveIdle() (int, error) { 197 | return s.GetSockOptInt(TCP_KEEPALIVE_IDLE) 198 | } 199 | 200 | // ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 201 | // 202 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc28 203 | // 204 | func (s *Socket) TCPKeepaliveCnt() (int, error) { 205 | return s.GetSockOptInt(TCP_KEEPALIVE_CNT) 206 | } 207 | 208 | // ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 209 | // 210 | // See: http://api.zeromq.org/3.2:zmq-getsockopt#toc29 211 | // 212 | func (s *Socket) TCPKeepaliveIntvl() (int, error) { 213 | return s.GetSockOptInt(TCP_KEEPALIVE_INTVL) 214 | } 215 | 216 | // Socket Option Setters 217 | 218 | // ZMQ_SNDHWM: Set high water mark for outbound messages. 219 | // 220 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc3 221 | // 222 | func (s *Socket) SetSndHWM(value int) error { 223 | return s.SetSockOptInt(SNDHWM, value) 224 | } 225 | 226 | // ZMQ_RCVHWM: Set high water mark for inbound messages. 227 | // 228 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc4 229 | // 230 | func (s *Socket) SetRcvHWM(value int) error { 231 | return s.SetSockOptInt(RCVHWM, value) 232 | } 233 | 234 | // ZMQ_AFFINITY: Set I/O thread affinity. 235 | // 236 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc5 237 | // 238 | func (s *Socket) SetAffinity(value uint64) error { 239 | return s.SetSockOptUInt64(AFFINITY, value) 240 | } 241 | 242 | // ZMQ_SUBSCRIBE: Establish message filter. 243 | // 244 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc6 245 | // 246 | func (s *Socket) SetSubscribe(value string) error { 247 | return s.SetSockOptString(SUBSCRIBE, value) 248 | } 249 | 250 | // ZMQ_UNSUBSCRIBE: Remove message filter. 251 | // 252 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc7 253 | // 254 | func (s *Socket) SetUnsubscribe(value string) error { 255 | return s.SetSockOptString(UNSUBSCRIBE, value) 256 | } 257 | 258 | // ZMQ_IDENTITY: Set socket identity. 259 | // 260 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc8 261 | // 262 | func (s *Socket) SetIdentity(value string) error { 263 | return s.SetSockOptString(IDENTITY, value) 264 | } 265 | 266 | // ZMQ_RATE: Set multicast data rate. 267 | // 268 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc9 269 | // 270 | func (s *Socket) SetRate(value int64) error { 271 | return s.SetSockOptInt64(RATE, value) 272 | } 273 | 274 | // ZMQ_RECOVERY_IVL: Set multicast recovery interval. 275 | // 276 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc10 277 | // 278 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 279 | return s.SetSockOptInt64(RECOVERY_IVL, int64(value/time.Millisecond)) 280 | } 281 | 282 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 283 | // 284 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc11 285 | // 286 | func (s *Socket) SetSndBuf(value uint64) error { 287 | return s.SetSockOptUInt64(SNDBUF, value) 288 | } 289 | 290 | // ZMQ_RCVBUF: Set kernel receive buffer size. 291 | // 292 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc12 293 | // 294 | func (s *Socket) SetRcvBuf(value uint64) error { 295 | return s.SetSockOptUInt64(RCVBUF, value) 296 | } 297 | 298 | // ZMQ_LINGER: Set linger period for socket shutdown. 299 | // 300 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc13 301 | // 302 | func (s *Socket) SetLinger(value time.Duration) error { 303 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 304 | } 305 | 306 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 307 | // 308 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc14 309 | // 310 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 311 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 312 | } 313 | 314 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 315 | // 316 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc15 317 | // 318 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 319 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 320 | } 321 | 322 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 323 | // 324 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc16 325 | // 326 | func (s *Socket) SetBacklog(value int) error { 327 | return s.SetSockOptInt(BACKLOG, value) 328 | } 329 | 330 | // ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size. 331 | // 332 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc17 333 | // 334 | func (s *Socket) SetMaxMsgSize(value int64) error { 335 | return s.SetSockOptInt64(MAXMSGSIZE, value) 336 | } 337 | 338 | // ZMQ_RCVTIMEO: Maximum time before a recv operation returns with EAGAIN. 339 | // 340 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc19 341 | // 342 | func (s *Socket) SetRcvTimeout(value time.Duration) error { 343 | return s.SetSockOptInt(RCVTIMEO, int(value/time.Millisecond)) 344 | } 345 | 346 | // ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN. 347 | // 348 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc20 349 | // 350 | func (s *Socket) SetSndTimeout(value time.Duration) error { 351 | return s.SetSockOptInt(SNDTIMEO, int(value/time.Millisecond)) 352 | } 353 | 354 | // ZMQ_IPV4ONLY: Use IPv4-only sockets. 355 | // 356 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc21 357 | // 358 | func (s *Socket) SetIPv4Only(value bool) error { 359 | if value { 360 | return s.SetSockOptInt(IPV4ONLY, 1) 361 | } 362 | return s.SetSockOptInt(IPV4ONLY, 0) 363 | } 364 | 365 | // ZMQ_DELAY_ATTACH_ON_CONNECT: Accept messages only when connections are made. 366 | // 367 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc22 368 | // 369 | func (s *Socket) SetDelayAttachOnConnect(value bool) error { 370 | if value { 371 | return s.SetSockOptInt(DELAY_ATTACH_ON_CONNECT, 1) 372 | } 373 | return s.SetSockOptInt(DELAY_ATTACH_ON_CONNECT, 0) 374 | } 375 | 376 | // ZMQ_ROUTER_MANDATORY: accept only routable messages on ROUTER sockets. 377 | // 378 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc23 379 | // 380 | func (s *Socket) SetROUTERMandatory(value bool) error { 381 | if value { 382 | return s.SetSockOptInt(ROUTER_MANDATORY, 1) 383 | } 384 | return s.SetSockOptInt(ROUTER_MANDATORY, 0) 385 | } 386 | 387 | // ZMQ_XPUB_VERBOSE: provide all subscription messages on XPUB sockets. 388 | // 389 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc24 390 | // 391 | func (s *Socket) SetXPUBVerbose(value bool) error { 392 | if value { 393 | return s.SetSockOptInt(XPUB_VERBOSE, 1) 394 | } 395 | return s.SetSockOptInt(XPUB_VERBOSE, 0) 396 | } 397 | 398 | // ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 399 | // 400 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc25 401 | // 402 | func (s *Socket) SetTCPKeepalive(value int) error { 403 | return s.SetSockOptInt(TCP_KEEPALIVE, value) 404 | } 405 | 406 | // ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS). 407 | // 408 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc26 409 | // 410 | func (s *Socket) SetTCPKeepaliveIdle(value int) error { 411 | return s.SetSockOptInt(TCP_KEEPALIVE_IDLE, value) 412 | } 413 | 414 | // ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 415 | // 416 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc27 417 | // 418 | func (s *Socket) SetTCPKeepaliveCnt(value int) error { 419 | return s.SetSockOptInt(TCP_KEEPALIVE_CNT, value) 420 | } 421 | 422 | // ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 423 | // 424 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc28 425 | // 426 | func (s *Socket) SetTCPKeepaliveIntvl(value int) error { 427 | return s.SetSockOptInt(TCP_KEEPALIVE_INTVL, value) 428 | } 429 | 430 | // ZMQ_TCP_ACCEPT_FILTER: Assign filters to allow new TCP connections. 431 | // 432 | // See: http://api.zeromq.org/3.2:zmq-setsockopt#toc29 433 | // 434 | func (s *Socket) SetTCPAcceptFilter(value string) error { 435 | return s.SetSockOptString(TCP_ACCEPT_FILTER, value) 436 | } 437 | -------------------------------------------------------------------------------- /zmqgen_4_0.go: -------------------------------------------------------------------------------- 1 | // +build zmq_4_x 2 | // 3 | 4 | package gozmq 5 | 6 | import ( 7 | "time" 8 | ) 9 | 10 | // This file was generated automatically. Changes made here will be lost. 11 | 12 | // Socket Option Getters 13 | 14 | // ZMQ_TYPE: Retrieve socket type. 15 | // 16 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc3 17 | // 18 | func (s *Socket) Type() (SocketType, error) { 19 | value, err := s.GetSockOptUInt64(TYPE) 20 | return SocketType(value), err 21 | } 22 | 23 | // ZMQ_RCVMORE: More message data parts to follow. 24 | // 25 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc4 26 | // 27 | func (s *Socket) RcvMore() (bool, error) { 28 | value, err := s.GetSockOptInt(RCVMORE) 29 | return value != 0, err 30 | } 31 | 32 | // ZMQ_SNDHWM: Retrieves high water mark for outbound messages. 33 | // 34 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc5 35 | // 36 | func (s *Socket) SndHWM() (int, error) { 37 | return s.GetSockOptInt(SNDHWM) 38 | } 39 | 40 | // ZMQ_RCVHWM: Retrieve high water mark for inbound messages. 41 | // 42 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc6 43 | // 44 | func (s *Socket) RcvHWM() (int, error) { 45 | return s.GetSockOptInt(RCVHWM) 46 | } 47 | 48 | // ZMQ_AFFINITY: Retrieve I/O thread affinity. 49 | // 50 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc7 51 | // 52 | func (s *Socket) Affinity() (uint64, error) { 53 | return s.GetSockOptUInt64(AFFINITY) 54 | } 55 | 56 | // ZMQ_IDENTITY: Retrieve socket identity. 57 | // 58 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc8 59 | // 60 | func (s *Socket) Identity() (string, error) { 61 | return s.GetSockOptString(IDENTITY) 62 | } 63 | 64 | // ZMQ_RATE: Retrieve multicast data rate. 65 | // 66 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc9 67 | // 68 | func (s *Socket) Rate() (int64, error) { 69 | return s.GetSockOptInt64(RATE) 70 | } 71 | 72 | // ZMQ_RECOVERY_IVL: Get multicast recovery interval. 73 | // 74 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc10 75 | // 76 | func (s *Socket) RecoveryIvl() (time.Duration, error) { 77 | ms, err := s.GetSockOptInt64(RECOVERY_IVL) 78 | return time.Duration(ms) * time.Millisecond, err 79 | } 80 | 81 | // ZMQ_SNDBUF: Retrieve kernel transmit buffer size. 82 | // 83 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc11 84 | // 85 | func (s *Socket) SndBuf() (uint64, error) { 86 | return s.GetSockOptUInt64(SNDBUF) 87 | } 88 | 89 | // ZMQ_RCVBUF: Retrieve kernel receive buffer size. 90 | // 91 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc12 92 | // 93 | func (s *Socket) RcvBuf() (uint64, error) { 94 | return s.GetSockOptUInt64(RCVBUF) 95 | } 96 | 97 | // ZMQ_LINGER: Retrieve linger period for socket shutdown. 98 | // 99 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc13 100 | // 101 | func (s *Socket) Linger() (time.Duration, error) { 102 | ms, err := s.GetSockOptInt(LINGER) 103 | return time.Duration(ms) * time.Millisecond, err 104 | } 105 | 106 | // ZMQ_RECONNECT_IVL: Retrieve reconnection interval. 107 | // 108 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc14 109 | // 110 | func (s *Socket) ReconnectIvl() (time.Duration, error) { 111 | ms, err := s.GetSockOptInt(RECONNECT_IVL) 112 | return time.Duration(ms) * time.Millisecond, err 113 | } 114 | 115 | // ZMQ_RECONNECT_IVL_MAX: Retrieve maximum reconnection interval. 116 | // 117 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc15 118 | // 119 | func (s *Socket) ReconnectIvlMax() (time.Duration, error) { 120 | ms, err := s.GetSockOptInt(RECONNECT_IVL_MAX) 121 | return time.Duration(ms) * time.Millisecond, err 122 | } 123 | 124 | // ZMQ_BACKLOG: Retrieve maximum length of the queue of outstanding connections. 125 | // 126 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc16 127 | // 128 | func (s *Socket) Backlog() (int, error) { 129 | return s.GetSockOptInt(BACKLOG) 130 | } 131 | 132 | // ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size. 133 | // 134 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc17 135 | // 136 | func (s *Socket) MaxMsgSize() (int64, error) { 137 | return s.GetSockOptInt64(MAXMSGSIZE) 138 | } 139 | 140 | // ZMQ_RCVTIMEO: Maximum time before a socket operation returns with EAGAIN. 141 | // 142 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc19 143 | // 144 | func (s *Socket) RcvTimeout() (time.Duration, error) { 145 | ms, err := s.GetSockOptInt(RCVTIMEO) 146 | return time.Duration(ms) * time.Millisecond, err 147 | } 148 | 149 | // ZMQ_SNDTIMEO: Maximum time before a socket operation returns with EAGAIN. 150 | // 151 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc20 152 | // 153 | func (s *Socket) SndTimeout() (time.Duration, error) { 154 | ms, err := s.GetSockOptInt(SNDTIMEO) 155 | return time.Duration(ms) * time.Millisecond, err 156 | } 157 | 158 | // ZMQ_IPV6: Retrieve IPv6 socket status. 159 | // 160 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc21 161 | // 162 | func (s *Socket) Ipv6() (bool, error) { 163 | value, err := s.GetSockOptInt(IPV6) 164 | return value != 0, err 165 | } 166 | 167 | // ZMQ_IPV4ONLY: Retrieve IPv4-only socket override status. 168 | // 169 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc22 170 | // 171 | func (s *Socket) IPv4Only() (bool, error) { 172 | value, err := s.GetSockOptInt(IPV4ONLY) 173 | return value != 0, err 174 | } 175 | 176 | // ZMQ_IMMEDIATE: Retrieve attach-on-connect value. 177 | // 178 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc23 179 | // 180 | func (s *Socket) Immediate() (bool, error) { 181 | value, err := s.GetSockOptInt(IMMEDIATE) 182 | return value != 0, err 183 | } 184 | 185 | // ZMQ_EVENTS: Retrieve socket event state. 186 | // 187 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc25 188 | // 189 | func (s *Socket) Events() (uint64, error) { 190 | return s.GetSockOptUInt64(EVENTS) 191 | } 192 | 193 | // ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 194 | // 195 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc27 196 | // 197 | func (s *Socket) TCPKeepalive() (int, error) { 198 | return s.GetSockOptInt(TCP_KEEPALIVE) 199 | } 200 | 201 | // ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT(or TCP_KEEPALIVE on some OS). 202 | // 203 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc28 204 | // 205 | func (s *Socket) TCPKeepaliveIdle() (int, error) { 206 | return s.GetSockOptInt(TCP_KEEPALIVE_IDLE) 207 | } 208 | 209 | // ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 210 | // 211 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc29 212 | // 213 | func (s *Socket) TCPKeepaliveCnt() (int, error) { 214 | return s.GetSockOptInt(TCP_KEEPALIVE_CNT) 215 | } 216 | 217 | // ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 218 | // 219 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc30 220 | // 221 | func (s *Socket) TCPKeepaliveIntvl() (int, error) { 222 | return s.GetSockOptInt(TCP_KEEPALIVE_INTVL) 223 | } 224 | 225 | // ZMQ_MECHANISM: Retrieve current security mechanism. 226 | // 227 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc31 228 | // 229 | func (s *Socket) Mechanism() (int, error) { 230 | return s.GetSockOptInt(MECHANISM) 231 | } 232 | 233 | // ZMQ_PLAIN_SERVER: Retrieve current PLAIN server role. 234 | // 235 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc32 236 | // 237 | func (s *Socket) PlainServer() (int, error) { 238 | return s.GetSockOptInt(PLAIN_SERVER) 239 | } 240 | 241 | // ZMQ_PLAIN_USERNAME: Retrieve current PLAIN username. 242 | // 243 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc33 244 | // 245 | func (s *Socket) PlainUsername() (string, error) { 246 | return s.GetSockOptString(PLAIN_USERNAME) 247 | } 248 | 249 | // ZMQ_PLAIN_PASSWORD: Retrieve current password. 250 | // 251 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc34 252 | // 253 | func (s *Socket) PlainPassword() (string, error) { 254 | return s.GetSockOptString(PLAIN_PASSWORD) 255 | } 256 | 257 | // ZMQ_CURVE_PUBLICKEY: Retrieve current CURVE public key. 258 | // 259 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc35 260 | // 261 | func (s *Socket) CurvePublickey() (string, error) { 262 | return s.GetSockOptString(CURVE_PUBLICKEY) 263 | } 264 | 265 | // ZMQ_CURVE_SECRETKEY: Retrieve current CURVE secret key. 266 | // 267 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc36 268 | // 269 | func (s *Socket) CurveSecretkey() (string, error) { 270 | return s.GetSockOptString(CURVE_SECRETKEY) 271 | } 272 | 273 | // ZMQ_CURVE_SERVERKEY: Retrieve current CURVE server key. 274 | // 275 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc37 276 | // 277 | func (s *Socket) CurveServerkey() (string, error) { 278 | return s.GetSockOptString(CURVE_SERVERKEY) 279 | } 280 | 281 | // ZMQ_ZAP_DOMAIN: Retrieve RFC 27 authentication domain. 282 | // 283 | // See: http://api.zeromq.org/4.0:zmq-getsockopt#toc38 284 | // 285 | func (s *Socket) ZapDomain() (string, error) { 286 | return s.GetSockOptString(ZAP_DOMAIN) 287 | } 288 | 289 | // Socket Option Setters 290 | 291 | // ZMQ_SNDHWM: Set high water mark for outbound messages. 292 | // 293 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc3 294 | // 295 | func (s *Socket) SetSndHWM(value int) error { 296 | return s.SetSockOptInt(SNDHWM, value) 297 | } 298 | 299 | // ZMQ_RCVHWM: Set high water mark for inbound messages. 300 | // 301 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc4 302 | // 303 | func (s *Socket) SetRcvHWM(value int) error { 304 | return s.SetSockOptInt(RCVHWM, value) 305 | } 306 | 307 | // ZMQ_AFFINITY: Set I/O thread affinity. 308 | // 309 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc5 310 | // 311 | func (s *Socket) SetAffinity(value uint64) error { 312 | return s.SetSockOptUInt64(AFFINITY, value) 313 | } 314 | 315 | // ZMQ_SUBSCRIBE: Establish message filter. 316 | // 317 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc6 318 | // 319 | func (s *Socket) SetSubscribe(value string) error { 320 | return s.SetSockOptString(SUBSCRIBE, value) 321 | } 322 | 323 | // ZMQ_UNSUBSCRIBE: Remove message filter. 324 | // 325 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc7 326 | // 327 | func (s *Socket) SetUnsubscribe(value string) error { 328 | return s.SetSockOptString(UNSUBSCRIBE, value) 329 | } 330 | 331 | // ZMQ_IDENTITY: Set socket identity. 332 | // 333 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc8 334 | // 335 | func (s *Socket) SetIdentity(value string) error { 336 | return s.SetSockOptString(IDENTITY, value) 337 | } 338 | 339 | // ZMQ_RATE: Set multicast data rate. 340 | // 341 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc9 342 | // 343 | func (s *Socket) SetRate(value int64) error { 344 | return s.SetSockOptInt64(RATE, value) 345 | } 346 | 347 | // ZMQ_RECOVERY_IVL: Set multicast recovery interval. 348 | // 349 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc10 350 | // 351 | func (s *Socket) SetRecoveryIvl(value time.Duration) error { 352 | return s.SetSockOptInt64(RECOVERY_IVL, int64(value/time.Millisecond)) 353 | } 354 | 355 | // ZMQ_SNDBUF: Set kernel transmit buffer size. 356 | // 357 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc11 358 | // 359 | func (s *Socket) SetSndBuf(value uint64) error { 360 | return s.SetSockOptUInt64(SNDBUF, value) 361 | } 362 | 363 | // ZMQ_RCVBUF: Set kernel receive buffer size. 364 | // 365 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc12 366 | // 367 | func (s *Socket) SetRcvBuf(value uint64) error { 368 | return s.SetSockOptUInt64(RCVBUF, value) 369 | } 370 | 371 | // ZMQ_LINGER: Set linger period for socket shutdown. 372 | // 373 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc13 374 | // 375 | func (s *Socket) SetLinger(value time.Duration) error { 376 | return s.SetSockOptInt(LINGER, int(value/time.Millisecond)) 377 | } 378 | 379 | // ZMQ_RECONNECT_IVL: Set reconnection interval. 380 | // 381 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc14 382 | // 383 | func (s *Socket) SetReconnectIvl(value time.Duration) error { 384 | return s.SetSockOptInt(RECONNECT_IVL, int(value/time.Millisecond)) 385 | } 386 | 387 | // ZMQ_RECONNECT_IVL_MAX: Set maximum reconnection interval. 388 | // 389 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc15 390 | // 391 | func (s *Socket) SetReconnectIvlMax(value time.Duration) error { 392 | return s.SetSockOptInt(RECONNECT_IVL_MAX, int(value/time.Millisecond)) 393 | } 394 | 395 | // ZMQ_BACKLOG: Set maximum length of the queue of outstanding connections. 396 | // 397 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc16 398 | // 399 | func (s *Socket) SetBacklog(value int) error { 400 | return s.SetSockOptInt(BACKLOG, value) 401 | } 402 | 403 | // ZMQ_MAXMSGSIZE: Maximum acceptable inbound message size. 404 | // 405 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc17 406 | // 407 | func (s *Socket) SetMaxMsgSize(value int64) error { 408 | return s.SetSockOptInt64(MAXMSGSIZE, value) 409 | } 410 | 411 | // ZMQ_RCVTIMEO: Maximum time before a recv operation returns with EAGAIN. 412 | // 413 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc19 414 | // 415 | func (s *Socket) SetRcvTimeout(value time.Duration) error { 416 | return s.SetSockOptInt(RCVTIMEO, int(value/time.Millisecond)) 417 | } 418 | 419 | // ZMQ_SNDTIMEO: Maximum time before a send operation returns with EAGAIN. 420 | // 421 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc20 422 | // 423 | func (s *Socket) SetSndTimeout(value time.Duration) error { 424 | return s.SetSockOptInt(SNDTIMEO, int(value/time.Millisecond)) 425 | } 426 | 427 | // ZMQ_IPV6: Enable IPv6 on socket. 428 | // 429 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc21 430 | // 431 | func (s *Socket) SetIpv6(value bool) error { 432 | if value { 433 | return s.SetSockOptInt(IPV6, 1) 434 | } 435 | return s.SetSockOptInt(IPV6, 0) 436 | } 437 | 438 | // ZMQ_IPV4ONLY: Use IPv4-only on socket. 439 | // 440 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc22 441 | // 442 | func (s *Socket) SetIPv4Only(value bool) error { 443 | if value { 444 | return s.SetSockOptInt(IPV4ONLY, 1) 445 | } 446 | return s.SetSockOptInt(IPV4ONLY, 0) 447 | } 448 | 449 | // ZMQ_IMMEDIATE: Queue messages only to completed connections. 450 | // 451 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc23 452 | // 453 | func (s *Socket) SetImmediate(value bool) error { 454 | if value { 455 | return s.SetSockOptInt(IMMEDIATE, 1) 456 | } 457 | return s.SetSockOptInt(IMMEDIATE, 0) 458 | } 459 | 460 | // ZMQ_ROUTER_MANDATORY: accept only routable messages on ROUTER sockets. 461 | // 462 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc24 463 | // 464 | func (s *Socket) SetROUTERMandatory(value bool) error { 465 | if value { 466 | return s.SetSockOptInt(ROUTER_MANDATORY, 1) 467 | } 468 | return s.SetSockOptInt(ROUTER_MANDATORY, 0) 469 | } 470 | 471 | // ZMQ_ROUTER_RAW: switch ROUTER socket to raw mode. 472 | // 473 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc25 474 | // 475 | func (s *Socket) SetROUTERRaw(value int) error { 476 | return s.SetSockOptInt(ROUTER_RAW, value) 477 | } 478 | 479 | // ZMQ_PROBE_ROUTER: bootstrap connections to ROUTER sockets. 480 | // 481 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc26 482 | // 483 | func (s *Socket) SetProbeROUTER(value int) error { 484 | return s.SetSockOptInt(PROBE_ROUTER, value) 485 | } 486 | 487 | // ZMQ_XPUB_VERBOSE: provide all subscription messages on XPUB sockets. 488 | // 489 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc27 490 | // 491 | func (s *Socket) SetXPUBVerbose(value bool) error { 492 | if value { 493 | return s.SetSockOptInt(XPUB_VERBOSE, 1) 494 | } 495 | return s.SetSockOptInt(XPUB_VERBOSE, 0) 496 | } 497 | 498 | // ZMQ_REQ_CORRELATE: match replies with requests. 499 | // 500 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc28 501 | // 502 | func (s *Socket) SetReqCorrelate(value int) error { 503 | return s.SetSockOptInt(REQ_CORRELATE, value) 504 | } 505 | 506 | // ZMQ_REQ_RELAXED: relax strict alternation between request and reply. 507 | // 508 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc29 509 | // 510 | func (s *Socket) SetReqRelaxed(value int) error { 511 | return s.SetSockOptInt(REQ_RELAXED, value) 512 | } 513 | 514 | // ZMQ_TCP_KEEPALIVE: Override SO_KEEPALIVE socket option. 515 | // 516 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc30 517 | // 518 | func (s *Socket) SetTCPKeepalive(value int) error { 519 | return s.SetSockOptInt(TCP_KEEPALIVE, value) 520 | } 521 | 522 | // ZMQ_TCP_KEEPALIVE_IDLE: Override TCP_KEEPCNT (or TCP_KEEPALIVE on some OS). 523 | // 524 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc31 525 | // 526 | func (s *Socket) SetTCPKeepaliveIdle(value int) error { 527 | return s.SetSockOptInt(TCP_KEEPALIVE_IDLE, value) 528 | } 529 | 530 | // ZMQ_TCP_KEEPALIVE_CNT: Override TCP_KEEPCNT socket option. 531 | // 532 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc32 533 | // 534 | func (s *Socket) SetTCPKeepaliveCnt(value int) error { 535 | return s.SetSockOptInt(TCP_KEEPALIVE_CNT, value) 536 | } 537 | 538 | // ZMQ_TCP_KEEPALIVE_INTVL: Override TCP_KEEPINTVL socket option. 539 | // 540 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc33 541 | // 542 | func (s *Socket) SetTCPKeepaliveIntvl(value int) error { 543 | return s.SetSockOptInt(TCP_KEEPALIVE_INTVL, value) 544 | } 545 | 546 | // ZMQ_TCP_ACCEPT_FILTER: Assign filters to allow new TCP connections. 547 | // 548 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc34 549 | // 550 | func (s *Socket) SetTCPAcceptFilter(value string) error { 551 | return s.SetSockOptString(TCP_ACCEPT_FILTER, value) 552 | } 553 | 554 | // ZMQ_PLAIN_SERVER: Set PLAIN server role. 555 | // 556 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc35 557 | // 558 | func (s *Socket) SetPlainServer(value int) error { 559 | return s.SetSockOptInt(PLAIN_SERVER, value) 560 | } 561 | 562 | // ZMQ_PLAIN_USERNAME: Set PLAIN security username. 563 | // 564 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc36 565 | // 566 | func (s *Socket) SetPlainUsername(value string) error { 567 | return s.SetSockOptString(PLAIN_USERNAME, value) 568 | } 569 | 570 | // ZMQ_PLAIN_PASSWORD: Set PLAIN security password. 571 | // 572 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc37 573 | // 574 | func (s *Socket) SetPlainPassword(value string) error { 575 | return s.SetSockOptString(PLAIN_PASSWORD, value) 576 | } 577 | 578 | // ZMQ_CURVE_SERVER: Set CURVE server role. 579 | // 580 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc38 581 | // 582 | func (s *Socket) SetCurveServer(value int) error { 583 | return s.SetSockOptInt(CURVE_SERVER, value) 584 | } 585 | 586 | // ZMQ_CURVE_PUBLICKEY: Set CURVE public key. 587 | // 588 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc39 589 | // 590 | func (s *Socket) SetCurvePublickey(value string) error { 591 | return s.SetSockOptString(CURVE_PUBLICKEY, value) 592 | } 593 | 594 | // ZMQ_CURVE_SECRETKEY: Set CURVE secret key. 595 | // 596 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc40 597 | // 598 | func (s *Socket) SetCurveSecretkey(value string) error { 599 | return s.SetSockOptString(CURVE_SECRETKEY, value) 600 | } 601 | 602 | // ZMQ_CURVE_SERVERKEY: Set CURVE server key. 603 | // 604 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc41 605 | // 606 | func (s *Socket) SetCurveServerkey(value string) error { 607 | return s.SetSockOptString(CURVE_SERVERKEY, value) 608 | } 609 | 610 | // ZMQ_ZAP_DOMAIN: Set RFC 27 authentication domain. 611 | // 612 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc42 613 | // 614 | func (s *Socket) SetZapDomain(value string) error { 615 | return s.SetSockOptString(ZAP_DOMAIN, value) 616 | } 617 | 618 | // ZMQ_CONFLATE: Keep only last message. 619 | // 620 | // See: http://api.zeromq.org/4.0:zmq-setsockopt#toc43 621 | // 622 | func (s *Socket) SetConflate(value bool) error { 623 | if value { 624 | return s.SetSockOptInt(CONFLATE, 1) 625 | } 626 | return s.SetSockOptInt(CONFLATE, 0) 627 | } 628 | --------------------------------------------------------------------------------