| package coap |
| |
| import ( |
| "net" |
| ) |
| |
| // ServeMux provides mappings from a common endpoint to handlers by |
| // request path. |
| type ServeMux struct { |
| m map[string]muxEntry |
| } |
| |
| type muxEntry struct { |
| h Handler |
| pattern string |
| } |
| |
| // NewServeMux creates a new ServeMux. |
| func NewServeMux() *ServeMux { return &ServeMux{m: make(map[string]muxEntry)} } |
| |
| // Does path match pattern? |
| func pathMatch(pattern, path string) bool { |
| if len(pattern) == 0 { |
| // should not happen |
| return false |
| } |
| n := len(pattern) |
| if pattern[n-1] != '/' { |
| return pattern == path |
| } |
| return len(path) >= n && path[0:n] == pattern |
| } |
| |
| // Find a handler on a handler map given a path string |
| // Most-specific (longest) pattern wins |
| func (mux *ServeMux) match(path string) (h Handler, pattern string) { |
| var n = 0 |
| for k, v := range mux.m { |
| if !pathMatch(k, path) { |
| continue |
| } |
| if h == nil || len(k) > n { |
| n = len(k) |
| h = v.h |
| pattern = v.pattern |
| } |
| } |
| return |
| } |
| |
| func notFoundHandler(l *net.UDPConn, a *net.UDPAddr, m Message) Message { |
| if m.IsConfirmable() { |
| return &DgramMessage{ |
| MessageBase{ |
| typ: Acknowledgement, |
| code: NotFound, |
| }, |
| } |
| } |
| return nil |
| } |
| |
| var _ = Handler(&ServeMux{}) |
| |
| // ServeCOAP handles a single COAP message. The message arrives from |
| // the given listener having originated from the given UDPAddr. |
| func (mux *ServeMux) ServeCOAP(l *net.UDPConn, a *net.UDPAddr, m Message) Message { |
| h, _ := mux.match(m.PathString()) |
| if h == nil { |
| h, _ = funcHandler(notFoundHandler), "" |
| } |
| // TODO: Rewrite path? |
| return h.ServeCOAP(l, a, m) |
| } |
| |
| // Handle configures a handler for the given path. |
| func (mux *ServeMux) Handle(pattern string, handler Handler) { |
| for pattern != "" && pattern[0] == '/' { |
| pattern = pattern[1:] |
| } |
| |
| if pattern == "" { |
| panic("http: invalid pattern " + pattern) |
| } |
| if handler == nil { |
| panic("http: nil handler") |
| } |
| |
| mux.m[pattern] = muxEntry{h: handler, pattern: pattern} |
| } |
| |
| // HandleFunc configures a handler for the given path. |
| func (mux *ServeMux) HandleFunc(pattern string, |
| f func(l *net.UDPConn, a *net.UDPAddr, m Message) Message) { |
| mux.Handle(pattern, FuncHandler(f)) |
| } |