github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/integration/messagebus/glue/server.go (about) 1 /* 2 * Glue - Robust Go and Javascript Socket Library 3 * Copyright (C) 2015 Roland Singer <roland.singer[at]desertbit.com> 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 // Package glue - Robust Go and Javascript Socket Library. 20 // This library is thread-safe. 21 package glue 22 23 import ( 24 "fmt" 25 "net" 26 "net/http" 27 "sync" 28 "time" 29 30 "github.com/mdaxf/iac/integration/messagebus/glue/backend" 31 "github.com/mdaxf/iac/integration/messagebus/glue/log" 32 ) 33 34 //####################// 35 //### Public Types ###// 36 //####################// 37 38 // OnNewSocketFunc is an event function. 39 type OnNewSocketFunc func(s *Socket) 40 41 //###################// 42 //### Server Type ###// 43 //###################// 44 45 // A Server represents a glue server which handles incoming socket connections. 46 type Server struct { 47 bs *backend.Server 48 options *Options 49 50 block bool 51 blockMutex sync.Mutex 52 onNewSocket OnNewSocketFunc 53 54 sockets map[string]*Socket // A map holding all active current sockets. 55 socketsMutex sync.Mutex 56 } 57 58 // NewServer creates a new glue server instance. 59 // One variadic arguments specifies the server options. 60 func NewServer(o ...Options) *Server { 61 // Get or create the options. 62 var options *Options 63 if len(o) > 0 { 64 options = &o[0] 65 } else { 66 options = &Options{} 67 } 68 69 // Set the default option values for unset values. 70 options.SetDefaults() 71 72 // Create a new backend server. 73 bs := backend.NewServer(len(options.HTTPHandleURL), options.EnableCORS, options.CheckOrigin) 74 75 // Create a new server value. 76 s := &Server{ 77 bs: bs, 78 options: options, 79 onNewSocket: func(*Socket) {}, // Initialize with dummy function to remove nil check. 80 sockets: make(map[string]*Socket), 81 } 82 83 // Set the backend server event function. 84 bs.OnNewSocketConnection(s.handleOnNewSocketConnection) 85 86 return s 87 } 88 89 // Block new incomming connections. 90 func (s *Server) Block(b bool) { 91 s.blockMutex.Lock() 92 defer s.blockMutex.Unlock() 93 94 s.block = b 95 } 96 97 // IsBlocked returns a boolean whenever new incoming connections should be blocked. 98 func (s *Server) IsBlocked() bool { 99 s.blockMutex.Lock() 100 defer s.blockMutex.Unlock() 101 102 return s.block 103 } 104 105 // OnNewSocket sets the event function which is 106 // triggered if a new socket connection was made. 107 // The event function must not block! As soon as the event function 108 // returns, the socket is added to the active sockets map. 109 func (s *Server) OnNewSocket(f OnNewSocketFunc) { 110 s.onNewSocket = f 111 } 112 113 // GetSocket obtains a socket by its ID. 114 // Returns nil if not found. 115 func (s *Server) GetSocket(id string) *Socket { 116 // Lock the mutex. 117 s.socketsMutex.Lock() 118 defer s.socketsMutex.Unlock() 119 120 // Obtain the socket. 121 socket, ok := s.sockets[id] 122 if !ok { 123 return nil 124 } 125 126 return socket 127 } 128 129 // Sockets returns a list of all current connected sockets. 130 // Hint: Sockets are added to the active sockets list before the OnNewSocket 131 // event function is called. 132 // Use the IsInitialized flag to determind if a socket is not ready yet... 133 func (s *Server) Sockets() []*Socket { 134 // Lock the mutex. 135 s.socketsMutex.Lock() 136 defer s.socketsMutex.Unlock() 137 138 // Create the slice. 139 list := make([]*Socket, len(s.sockets)) 140 141 // Add all sockets from the map. 142 i := 0 143 for _, s := range s.sockets { 144 list[i] = s 145 i++ 146 } 147 148 return list 149 } 150 151 // Release this package. This will block all new incomming socket connections 152 // and close all current connected sockets. 153 func (s *Server) Release() { 154 // Block all new incomming socket connections. 155 s.Block(true) 156 157 // Wait for a little moment, so new incomming sockets are added 158 // to the sockets active list. 159 time.Sleep(200 * time.Millisecond) 160 161 // Close all current connected sockets. 162 sockets := s.Sockets() 163 for _, s := range sockets { 164 s.Close() 165 } 166 } 167 168 // Run starts the server and listens for incoming socket connections. 169 // This is a blocking method. 170 func (s *Server) Run() error { 171 // Skip if set to none. 172 log.L.Debug("start the glue server") 173 log.L.Debug("HTTPSocketType: %v", s.options.HTTPSocketType) 174 log.L.Debug("HTTPHandleURL: %v", s.options.HTTPHandleURL) 175 if s.options.HTTPSocketType != HTTPSocketTypeNone { 176 // Set the base glue HTTP handler. 177 http.Handle(s.options.HTTPHandleURL, s) 178 179 // Start the http server. 180 if s.options.HTTPSocketType == HTTPSocketTypeUnix { 181 // Listen on the unix socket. 182 l, err := net.Listen("unix", s.options.HTTPListenAddress) 183 if err != nil { 184 return fmt.Errorf("Listen: %v", err) 185 } 186 187 // Start the http server. 188 err = http.Serve(l, nil) 189 if err != nil { 190 return fmt.Errorf("Serve: %v", err) 191 } 192 } else if s.options.HTTPSocketType == HTTPSocketTypeTCP { 193 // Start the http server. 194 err := http.ListenAndServe(s.options.HTTPListenAddress, nil) 195 if err != nil { 196 return fmt.Errorf("ListenAndServe: %v", err) 197 } 198 } else { 199 return fmt.Errorf("invalid socket options type: %v", s.options.HTTPSocketType) 200 } 201 } else { 202 // HINT: This is only a placeholder until the internal glue TCP server is implemented. 203 w := make(chan struct{}) 204 <-w 205 } 206 207 return nil 208 } 209 210 // ServeHTTP implements the HTTP Handler interface of the http package. 211 func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 212 s.bs.ServeHTTP(w, r) 213 } 214 215 //########################// 216 //### Server - Private ###// 217 //########################// 218 219 func (s *Server) handleOnNewSocketConnection(bs backend.BackendSocket) { 220 // Close the socket if incomming connections should be blocked. 221 if s.IsBlocked() { 222 bs.Close() 223 return 224 } 225 226 // Create a new socket value. 227 // The goroutines are started automatically. 228 newSocket(s, bs) 229 }