gopkg.in/hugelgupf/u-root.v2@v2.0.0-20180831055005-3f8fdb0ce09d/cmds/time_sos/server.go (about)

     1  // Copyright 2018 the u-root 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  	"encoding/json"
     9  	"fmt"
    10  	"html/template"
    11  	"io/ioutil"
    12  	"log"
    13  	"net/http"
    14  
    15  	"github.com/gorilla/mux"
    16  	"github.com/u-root/u-root/pkg/sos"
    17  )
    18  
    19  const (
    20  	DefHtmlPage = `
    21    <head>
    22    <style>
    23      table {
    24        font-family: arial, sans-serif;
    25        border-collapse: collapse;
    26        width: 100%;
    27      }
    28      td, th {
    29        border: 1px solid #dddddd;
    30        text-align: left;
    31        padding: 8px;
    32      }
    33      input {
    34        font-size: 120%;
    35      }
    36    </style>
    37    <script>
    38  		function sendAutoSet() {
    39  			fetch("http://localhost:{{.Port}}/auto", {
    40  				method: 'Post'
    41  			})
    42  			.then(r => r.json())
    43  			.then( s => {
    44  				if (s !== null) {
    45  					alert(s.Error);
    46  					window.location.reload();
    47  				}
    48  				else {
    49  					window.location.reload();
    50  				}
    51  			})
    52  			.catch(err => alert(err))
    53  		}
    54  
    55  		function sendManSet() {
    56  			d = document.getElementById("date_field").value
    57  			t = document.getElementById("time_field").value
    58  			fetch("http://localhost:{{.Port}}/manual", {
    59  				method: 'Post',
    60  				headers: {
    61  					'Accept': 'application/json',
    62  					'Content-Type': 'application/json'
    63  				},
    64  				body: JSON.stringify({
    65  					Date: d,
    66  					Time: t
    67  				})
    68  			})
    69  			.then(r => r.json())
    70  			.then( s => {
    71  				if (s !== null) {
    72  					alert(s.Error);
    73  					window.location.reload();
    74  				}
    75  				else {
    76  					window.location.reload();
    77  				}
    78  			})
    79  			.catch(err => alert(err))
    80  		}
    81  
    82  		function setOnLoad(date, time) {
    83  			document.getElementById("date_field").setAttribute("value", date)
    84  			document.getElementById("time_field").setAttribute("value", time)
    85  		}
    86    </script>
    87    </head>
    88  	<body onload="setOnLoad({{.Date}}, {{.Time}})">
    89  		<h1>System Time Settings</h2>
    90  		<table style="width:100%">
    91  			<tr>
    92  				<td><input type="date" id="date_field"></td>
    93  				<td><input type="time" id="time_field"></td>
    94  				<td><input type="submit" id="button" value="Auto-Set" onclick=sendAutoSet()></td>
    95  			</tr>
    96  			<tr>
    97  				<td colspan="3"><input type="submit" id="button" value="Save" onclick=sendManSet()></td>
    98  			</tr>
    99  		</table>
   100  	</body>
   101    `
   102  )
   103  
   104  type TimeServer struct {
   105  	service *TimeService
   106  }
   107  
   108  var (
   109  	Port uint
   110  )
   111  
   112  func (ts *TimeServer) displayStateHandle(w http.ResponseWriter, r *http.Request) {
   113  	ts.service.Update()
   114  	timeData := struct {
   115  		Date string
   116  		Time string
   117  		Port uint
   118  	}{ts.service.Date, ts.service.Time, Port}
   119  	var tmpl *template.Template
   120  	file, err := ioutil.ReadFile(sos.HTMLPath("time.html"))
   121  	if err == nil {
   122  		html := string(file)
   123  		tmpl = template.Must(template.New("SoS").Parse(html))
   124  	} else {
   125  		tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage))
   126  	}
   127  	tmpl.Execute(w, timeData)
   128  }
   129  
   130  func (ts *TimeServer) autoHandle(w http.ResponseWriter, r *http.Request) {
   131  	if err := ts.service.AutoSetTime(); err != nil {
   132  		log.Printf("error: %v", err)
   133  		w.WriteHeader(http.StatusInternalServerError)
   134  		json.NewEncoder(w).Encode(struct{ Error string }{fmt.Sprintf("Unable to set time. Are you online?")})
   135  		return
   136  	}
   137  	json.NewEncoder(w).Encode(nil)
   138  }
   139  
   140  type TimeJsonMsg struct {
   141  	Date string
   142  	Time string
   143  }
   144  
   145  func (ts *TimeServer) manHandle(w http.ResponseWriter, r *http.Request) {
   146  	var msg TimeJsonMsg
   147  	decoder := json.NewDecoder(r.Body)
   148  	defer r.Body.Close()
   149  	if err := decoder.Decode(&msg); err != nil {
   150  		log.Printf("error: %v", err)
   151  		w.WriteHeader(http.StatusBadRequest)
   152  		json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
   153  		return
   154  	}
   155  	if err := ts.service.ManSetTime(msg); err != nil {
   156  		log.Printf("error: %v", err)
   157  		w.WriteHeader(http.StatusInternalServerError)
   158  		json.NewEncoder(w).Encode(struct{ Error string }{err.Error()})
   159  		return
   160  	}
   161  	json.NewEncoder(w).Encode(nil)
   162  }
   163  
   164  func (ts *TimeServer) buildRouter() *mux.Router {
   165  	r := mux.NewRouter()
   166  	r.HandleFunc("/", ts.displayStateHandle).Methods("GET")
   167  	r.HandleFunc("/auto", ts.autoHandle).Methods("POST")
   168  	r.HandleFunc("/manual", ts.manHandle).Methods("POST")
   169  	r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css")))))
   170  	return r
   171  }
   172  
   173  // Start opens the server at localhost:{port}, where port is provided automatically
   174  // by the SoS.
   175  func (ts *TimeServer) Start() {
   176  	listener, port, err := sos.GetListener()
   177  	if err != nil {
   178  		log.Fatalf("error: %v", err)
   179  	}
   180  	Port = port
   181  	fmt.Println(sos.StartServiceServer(ts.buildRouter(), "time", listener, Port))
   182  }
   183  
   184  // NewTimeServer creates a server with the given TimeService.
   185  func NewTimeServer(service *TimeService) *TimeServer {
   186  	return &TimeServer{
   187  		service: service,
   188  	}
   189  }