// Package ddp implements the MeteorJS DDP protocol over websockets. Fallback // to longpolling is NOT supported (and is not planned on ever being supported // by this library). We will try to model the library after `net/http` - right // now the library is barebones and doesn't provide the pluggability of http. // However, that's the goal for the package eventually. package ddp import ( "fmt" "log" "sync" "time" ) // debugLog is true if we should log debugging information about the connection var debugLog = true // The main file contains common utility types. // ------------------------------------------------------------------- // idManager provides simple incrementing IDs for ddp messages. type idManager struct { // nextID is the next ID for API calls nextID uint64 // idMutex is a mutex to protect ID updates idMutex *sync.Mutex } // newidManager creates a new instance and sets up resources. func newidManager() *idManager { return &idManager{idMutex: new(sync.Mutex)} } // newID issues a new ID for use in calls. func (id *idManager) newID() string { id.idMutex.Lock() next := id.nextID id.nextID++ id.idMutex.Unlock() return fmt.Sprintf("%x", next) } // ------------------------------------------------------------------- // pingTracker tracks in-flight pings. type pingTracker struct { handler func(error) timeout time.Duration timer *time.Timer } // ------------------------------------------------------------------- // Call represents an active RPC call. type Call struct { ID string // The uuid for this method call ServiceMethod string // The name of the service and method to call. Args interface{} // The argument to the function (*struct). Reply interface{} // The reply from the function (*struct). Error error // After completion, the error status. Done chan *Call // Strobes when call is complete. Owner *Client // Client that owns the method call } // done removes the call from any owners and strobes the done channel with itself. func (call *Call) done() { delete(call.Owner.calls, call.ID) select { case call.Done <- call: // ok default: // We don't want to block here. It is the caller's responsibility to make // sure the channel has enough buffer space. See comment in Go(). if debugLog { log.Println("rpc: discarding Call reply due to insufficient Done chan capacity") } } }