| 144 | } |
| 145 | |
| 146 | func newWebsocketCaller(ctx context.Context, uri string, timeout time.Duration, notifier Notifier) (*websocketCaller, error) { |
| 147 | var header = http.Header{} |
| 148 | conn, _, err := websocket.DefaultDialer.Dial(uri, header) |
| 149 | if err != nil { |
| 150 | return nil, err |
| 151 | } |
| 152 | |
| 153 | sendChan := make(chan *sendRequest, 16) |
| 154 | var wg sync.WaitGroup |
| 155 | ctx, cancel := context.WithCancel(ctx) |
| 156 | w := &websocketCaller{conn: conn, wg: &wg, cancel: cancel, sendChan: sendChan, timeout: timeout} |
| 157 | processor := NewResponseProcessor() |
| 158 | wg.Add(1) |
| 159 | go func() { // routine:recv |
| 160 | defer wg.Done() |
| 161 | defer cancel() |
| 162 | for { |
| 163 | select { |
| 164 | case <-ctx.Done(): |
| 165 | return |
| 166 | default: |
| 167 | } |
| 168 | var resp websocketResponse |
| 169 | if err := conn.ReadJSON(&resp); err != nil { |
| 170 | select { |
| 171 | case <-ctx.Done(): |
| 172 | return |
| 173 | default: |
| 174 | } |
| 175 | log.Printf("conn.ReadJSON|err:%v", err.Error()) |
| 176 | return |
| 177 | } |
| 178 | if resp.Id == nil { // RPC notifications |
| 179 | if notifier != nil { |
| 180 | switch resp.Method { |
| 181 | case "aria2.onDownloadStart": |
| 182 | notifier.OnDownloadStart(resp.Params) |
| 183 | case "aria2.onDownloadPause": |
| 184 | notifier.OnDownloadPause(resp.Params) |
| 185 | case "aria2.onDownloadStop": |
| 186 | notifier.OnDownloadStop(resp.Params) |
| 187 | case "aria2.onDownloadComplete": |
| 188 | notifier.OnDownloadComplete(resp.Params) |
| 189 | case "aria2.onDownloadError": |
| 190 | notifier.OnDownloadError(resp.Params) |
| 191 | case "aria2.onBtDownloadComplete": |
| 192 | notifier.OnBtDownloadComplete(resp.Params) |
| 193 | default: |
| 194 | log.Printf("unexpected notification: %s", resp.Method) |
| 195 | } |
| 196 | } |
| 197 | continue |
| 198 | } |
| 199 | processor.Process(resp.clientResponse) |
| 200 | } |
| 201 | }() |
| 202 | wg.Add(1) |
| 203 | go func() { // routine:send |